From ac29184521f59c8bffa14a610b546b7099ce42f1 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Mon, 8 Mar 2021 16:47:55 +0200 Subject: [PATCH 001/429] deserialization sinks --- .../CWE-502/DeserializedDelegate.ql | 2 +- .../CWE-502/UnsafeDeserialization.ql | 14 +- .../UnsafeDeserializationUntrustedInput.qhelp | 11 + .../UnsafeDeserializationUntrustedInput.ql | 52 +- ...afeDeserializationUntrustedInputTypeBad.cs | 13 + ...feDeserializationUntrustedInputTypeGood.cs | 20 + .../dataflow/UnsafeDeserialization.qll | 669 +++++++++++++++++- .../csharp/serialization/Deserializers.qll | 547 +++++++++++++- .../BinaryFormatterBad.cs | 12 + .../DataContractJsonSerializerBad.cs | 13 + .../DataContractJsonSerializerGood.cs | 13 + .../DataContractSerializerBad.cs | 13 + .../DataContractSerializerGood.cs | 13 + .../UnsafeDeserialization/ExtractorOptions.cs | 2 +- .../ResourceReaderBad.cs | 17 + .../UnsafeDeserialization.expected | 6 + .../XmlObjectSerializerBad.cs | 13 + .../XmlObjectSerializerGood.cs | 13 + .../UnsafeDeserialization/XmlSerializerBad.cs | 13 + .../XmlSerializerGood.cs | 13 + .../BinaryFormatterUntrustedInputBad.cs | 14 + .../BinaryFormatterUntrustedInputGood.cs | 13 + ...ContractJsonSerializerUntrustedInputBad.cs | 15 + ...ontractJsonSerializerUntrustedInputGood.cs | 22 + ...DataContractSerializerUntrustedInputBad.cs | 15 + ...ataContractSerializerUntrustedInputGood.cs | 22 + .../ExtractorOptions.cs | 2 +- .../ResourceReaderUntrustedInputBad.cs | 19 + .../ResourceReaderUntrustedInputGood.cs | 19 + ...safeDeserializationUntrustedInput.expected | 142 +++- ...UnsafeDeserializationUntrustedInputGood.cs | 4 +- .../XmlObjectSerializerUntrustedInputBad.cs | 15 + .../XmlObjectSerializerUntrustedInputGood.cs | 22 + .../XmlSerializerUntrustedInputBad.cs | 15 + .../XmlSerializerUntrustedInputGood.cs | 22 + 35 files changed, 1755 insertions(+), 75 deletions(-) create mode 100644 csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeBad.cs create mode 100644 csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputGood.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs create mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputGood.cs diff --git a/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql b/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql index 31d28311908..75708e712dc 100644 --- a/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql +++ b/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.serialization.Deserializers from Call deserialization, Cast cast where - deserialization.getTarget() instanceof UnsafeDeserializer and + deserialization.getTarget() instanceof UnsafeDeserializerCallable and cast.getExpr() = deserialization and cast.getTargetType() instanceof SystemLinqExpressions::DelegateExtType select deserialization, "Deserialization of delegate type." diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 40022d40573..dedf21a1859 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -13,7 +13,17 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization -from Call deserializeCall, Sink sink -where deserializeCall.getAnArgument() = sink.asExpr() +from Call deserializeCall, ObjectMethodSink sink +where + deserializeCall.getAnArgument() = sink.asExpr() and + not exists( + DataFlow::PathNode constructor, DataFlow::PathNode usage, + SafeConstructorTrackingConfig constructorTracking + | + constructorTracking.hasFlowPath(constructor, usage) and + usage.getNode().asExpr().getParent() = sink.asExpr().getParent() + ) + or + exists(ConstructorOrStaticMethodSink sink2 | deserializeCall.getAnArgument() = sink2.asExpr()) select deserializeCall, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp index 3ba934ba391..7c8781b15a1 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp @@ -27,6 +27,17 @@ it may be necessary to use a different deserialization framework.

+

In the following example potentially untrusted stream and type is deserialized using a +DataContractJsonSerializer which is known to be vulnerable with user supplied types.

+ + + +

To fix this specific vulnerability, we are using hardcoded +Plain Old CLR Object (POCO) type. In other cases, +it may be necessary to use a different deserialization framework.

+ + + diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 80a3762a8bc..0932517acce 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -13,8 +13,54 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph +import semmle.code.csharp.security.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Local -from TaintTrackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows to unsafe deserializer.", source.getNode(), +class RemoteSource extends Source { + RemoteSource() { this instanceof RemoteFlowSource } +} + +class LocalSource extends Source { + LocalSource() { this instanceof LocalFlowSource } +} + +from + TaintToObjectMethodTrackingConfig taintTracking, DataFlow::PathNode userInput, + DataFlow::PathNode deserializeCall +where + // all flows from user input to deserialization with weak and strong type serializers + taintTracking.hasFlowPath(userInput, deserializeCall) and + // intersect with strong types, but user controlled or weak types deserialization usages + ( + exists( + DataFlow::PathNode weakTypeCreation, DataFlow::PathNode weakTypeUsage, + WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking + | + weakTypeDeserializerTracking.hasFlowPath(weakTypeCreation, weakTypeUsage) and + weakTypeUsage.getNode().asExpr().getParent() = deserializeCall.getNode().asExpr().getParent() + ) + or + exists( + TaintToObjectTypeTrackingConfig userControlledTypeTracking, + DataFlow::PathNode taintedTypeUsage, DataFlow::PathNode userInput2 + | + userControlledTypeTracking.hasFlowPath(userInput2, taintedTypeUsage) and + taintedTypeUsage.getNode().asExpr().getParent() = + deserializeCall.getNode().asExpr().getParent() + ) + ) and + // exclude deserialization flows with safe instances (i.e. JavaScriptSerializer without resolver) + not exists( + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, + DataFlow::PathNode safeTypeUsage + | + safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and + safeTypeUsage.getNode().asExpr().getParent() = deserializeCall.getNode().asExpr().getParent() + ) + or + // no type check needed - straightforward taint -> sink + exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 | + taintTracking2.hasFlowPath(userInput, deserializeCall) + ) +select deserializeCall, userInput, deserializeCall, "$@ flows to unsafe deserializer.", userInput, "User-provided data" diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeBad.cs b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeBad.cs new file mode 100644 index 00000000000..4e439cab8c7 --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeBad.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization.Json; +using System.IO; +using System; + +class BadDataContractJsonSerializer +{ + public static object Deserialize(string type, Stream s) + { + // BAD: stream and type are potentially untrusted + var ds = new DataContractJsonSerializer(Type.GetType(type)); + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeGood.cs b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeGood.cs new file mode 100644 index 00000000000..1a97f009120 --- /dev/null +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputTypeGood.cs @@ -0,0 +1,20 @@ +using System.Runtime.Serialization.Json; +using System.IO; +using System; + +class Poco +{ + public int Count; + + public string Comment; +} + +class GoodDataContractJsonSerializer +{ + public static Poco Deserialize(Stream s) + { + // GOOD: while stream is potentially untrusted, the instantiated type is hardcoded + var ds = new DataContractJsonSerializer(typeof(Poco)); + return (Poco)ds.ReadObject(s); + } +} diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 0943774d8cd..f63d0ef7021 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,6 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers /** @@ -17,7 +16,12 @@ module UnsafeDeserialization { /** * A data flow sink for unsafe deserialization vulnerabilities. */ - abstract class Sink extends DataFlow::Node { } + abstract class ObjectMethodSink extends DataFlow::Node { } + + /** + * A data flow sink for unsafe deserialization vulnerabilities. + */ + abstract class ConstructorOrStaticMethodSink extends DataFlow::Node { } /** * A sanitizer for unsafe deserialization vulnerabilities. @@ -25,57 +29,654 @@ module UnsafeDeserialization { abstract class Sanitizer extends DataFlow::Node { } /** - * A taint-tracking configuration for reasoning about unsafe deserialization. + * User input to object method call deserialization flow tracking. */ - class TaintTrackingConfig extends TaintTracking::Configuration { - TaintTrackingConfig() { this = "UnsafeDeserialization" } + class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration { + TaintToObjectMethodTrackingConfig() { this = "UnsafeDeserialization1" } override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + override predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMethodSink } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } - class RemoteSource extends Source { - RemoteSource() { this instanceof RemoteFlowSource } + /** + * User input to static method or constructor call deserialization flow tracking. + */ + class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration { + TaintToConstructorOrStaticMethodTrackingConfig() { this = "UnsafeDeserialization2" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof ConstructorOrStaticMethodSink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } - /** A call to an unsafe deserializer. */ - class UnsafeDeserializerSink extends Sink { - UnsafeDeserializerSink() { - exists(Call c | - this.asExpr() = c.getAnArgument() and - c.getTarget() instanceof UnsafeDeserializer + /** + * User input to instance type flow tracking. + */ + class TaintToObjectTypeTrackingConfig extends TaintTracking::Configuration { + TaintToObjectTypeTrackingConfig() { this = "TaintToObjectTypeTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + m instanceof UnsafeDeserializerCallable and + sink.asExpr() = mc.getQualifier() ) } - } - private class JavaScriptSerializerClass extends Class { - JavaScriptSerializerClass() { - this.hasQualifiedName("System.Web.Script.Serialization.JavaScriptSerializer") + override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + m.getDeclaringType().hasQualifiedName("System.Type") and + m.hasName("GetType") and + m.isStatic() and + n1.asExpr() = mc.getArgument(0) and + n2.asExpr() = mc + ) + or + exists(ObjectCreation oc | + n1.asExpr() = oc.getAnArgument() and + n2.asExpr() = oc and + oc.getObjectType() instanceof StrongTypeDeserializer + ) } } /** - * An unsafe use of a JavaScript deserializer. That is, a use with a custom type-resolver - * (constructor parameter). + * Unsafe deserializer creation to usage tracking config. */ - class JavaScriptSerializerSink extends Sink { - JavaScriptSerializerSink() { + class WeakTypeCreationToUsageTrackingConfig extends TaintTracking::Configuration { + WeakTypeCreationToUsageTrackingConfig() { this = "DeserializerCreationToUsageTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { exists(ObjectCreation oc | - oc.getTarget().getDeclaringType() instanceof JavaScriptSerializerClass and - oc.getTarget().getNumberOfParameters() > 0 and - exists(MethodCall mc, Method m | - m = mc.getTarget() and - m.getDeclaringType() instanceof JavaScriptSerializerClass and - ( - m.hasName("Deserialize") or - m.hasName("DeserializeObject") - ) and - this.asExpr() = mc.getAnArgument() and - DataFlow::localFlow(DataFlow::exprNode(oc), DataFlow::exprNode(mc.getQualifier())) - ) + oc.getObjectType() instanceof WeakTypeDeserializer and + source.asExpr() = oc + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + m instanceof UnsafeDeserializerCallable and + sink.asExpr() = mc.getQualifier() + ) + } + } + + /** + * Safe deserializer creation to usage tracking config. + */ + abstract class SafeConstructorTrackingConfig extends TaintTracking::Configuration { + bindingset[this] + SafeConstructorTrackingConfig() { any() } + } + + /** BinaryFormatter */ + predicate isBinaryFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof BinaryFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() + or + m instanceof BinaryFormatterUnsafeDeserializeMethod and + not mc.getArgument(0).hasValue() + or + m instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod and + not mc.getArgument(0).hasValue() + ) + } + + abstract class BinaryFormatterSink extends ObjectMethodSink { } + + class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { + BinaryFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isBinaryFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** SoapFormatter */ + predicate isSoapFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof SoapFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() + } + + abstract class SoapFormatterSink extends ObjectMethodSink { } + + class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { + SoapFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isSoapFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** ObjectStateFormatter */ + predicate isObjectStateFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof ObjectStateFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() + } + + abstract class ObjectStateFormatterSink extends ObjectMethodSink { } + + class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { + ObjectStateFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isObjectStateFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** NetDataContractSerializer */ + predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof NetDataContractSerializerDeserializeMethod and + not mc.getArgument(0).hasValue() + or + m instanceof NetDataContractSerializerReadObjectMethod and + not mc.getArgument(0).hasValue() + ) + } + + abstract class NetDataContractSerializerSink extends ObjectMethodSink { } + + class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { + NetDataContractSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isNetDataContractSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** DataContractJsonSerializer */ + predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof DataContractJsonSerializerReadObjectMethod and + not mc.getArgument(0).hasValue() + } + + abstract class DataContractJsonSerializerSink extends ObjectMethodSink { } + + class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { + DataContractJsonSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isDataContractJsonSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + DataContractJsonSafeConstructorTrackingConfiguration() { + this = "DataContractJsonSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + DataContractJsonSerializerClass and + source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and + source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isDataContractJsonSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** JavaScriptSerializer */ + predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof JavaScriptSerializerClassDeserializeMethod and + not mc.getArgument(0).hasValue() + or + m instanceof JavaScriptSerializerClassDeserializeObjectMethod and + not mc.getArgument(0).hasValue() + ) + } + + abstract class JavaScriptSerializerSink extends ObjectMethodSink { } + + class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { + JavaScriptSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isJavaScriptSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + JavaScriptSerializerSafeConstructorTrackingConfiguration() { + this = "JavaScriptSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + JavaScriptSerializerClass and + source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() = 0 + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isJavaScriptSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** XmlObjectSerializer */ + predicate isXmlObjectSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlObjectSerializerReadObjectMethod and + not mc.getArgument(0).hasValue() and + not mc.targetIsLocalInstance() + } + + abstract class XmlObjectSerializerSink extends ObjectMethodSink { } + + class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { + XmlObjectSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlObjectSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlObjectSerializerDerivedConstructorTrackingConfiguration() { + this = "XmlObjectSerializerDerivedConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType().getABaseType+() instanceof + XmlObjectSerializerClass and + not ( + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + DataContractSerializerClass or + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + NetDataContractSerializerClass + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlObjectSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** XmlSerializer */ + predicate isXmlSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlSerializerDeserializeMethod and + not mc.getArgument(0).hasValue() + } + + abstract class XmlSerializerSink extends ObjectMethodSink { } + + class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { + XmlSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlSerializerSafeConstructorTrackingConfiguration() { + this = "XmlSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof XmlSerializerClass and + source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and + source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** DataContractSerializer */ + predicate isDataContractSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof DataContractSerializerReadObjectMethod + or + m instanceof XmlObjectSerializerReadObjectMethod + ) and + not mc.getArgument(0).hasValue() + } + + abstract class DataContractSerializerSink extends ObjectMethodSink { } + + class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { + DataContractSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isDataContractSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + DataContractSerializerSafeConstructorTrackingConfiguration() { + this = "DataContractSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + DataContractSerializerClass and + source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and + source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isDataContractSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** XmlMessageFormatter */ + predicate isXmlMessageFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlMessageFormatterReadMethod and + not mc.getArgument(0).hasValue() + } + + abstract class XmlMessageFormatterSink extends ObjectMethodSink { } + + class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { + XmlMessageFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlMessageFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlMessageFormatterSafeConstructorTrackingConfiguration() { + this = "XmlMessageFormatterSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof + XmlMessageFormatterClass and + source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and + source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlMessageFormatterCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } + } + + /** LosFormatter */ + predicate isLosFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof LosFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() + } + + abstract class LosFormatterSink extends ObjectMethodSink { } + + class LosFormatterDeserializeMethodSink extends LosFormatterSink { + LosFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isLosFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** fastJSON */ + predicate isFastJsonCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof FastJsonClassToObjectMethod and + not mc.getArgument(0).hasValue() + } + + abstract class FastJsonSink extends ConstructorOrStaticMethodSink { } + + class FastJsonDeserializeMethodSink extends FastJsonSink { + FastJsonDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isFastJsonCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** Activity */ + predicate isActivityCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof ActivityLoadMethod and + not mc.getArgument(0).hasValue() + } + + abstract class ActivitySink extends ObjectMethodSink { } + + class ActivityDeserializeMethodSink extends ActivitySink { + ActivityDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isActivityCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** ResourceReader */ + predicate isResourceReaderCall(Call mc, Constructor m) { + m = mc.getTarget() and + m instanceof ResourceReaderConstructor and + not mc.getArgument(0).hasValue() + } + + abstract class ResourceReaderSink extends ConstructorOrStaticMethodSink { } + + class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { + ResourceReaderDeserializeMethodSink() { + exists(Call mc, Constructor m | + isResourceReaderCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** BinaryMessageFormatter */ + predicate isBinaryMessageFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof BinaryMessageFormatterReadMethod and + not mc.getArgument(0).hasValue() + } + + abstract class BinaryMessageFormatterSink extends ObjectMethodSink { } + + class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { + BinaryMessageFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isBinaryMessageFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** XamlReader */ + predicate isXamlReaderCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof XamlReaderParseMethod + or + m instanceof XamlReaderLoadMethod + or + m instanceof XamlReaderLoadAsyncMethod + ) and + not mc.getArgument(0).hasValue() + } + + abstract class XamlReaderSink extends ConstructorOrStaticMethodSink { } + + class XamlReaderDeserializeMethodSink extends XamlReaderSink { + XamlReaderDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXamlReaderCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** ProxyObject */ + predicate isProxyObjectCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof ProxyObjectDecodeValueMethod + or + m instanceof ProxyObjectDecodeSerializedObjectMethod + ) and + not mc.getArgument(0).hasValue() + } + + abstract class ProxyObjectSink extends ObjectMethodSink { } + + class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { + ProxyObjectDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isProxyObjectCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** SweetJayson */ + predicate isSweetJaysonCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof JaysonConverterToObjectMethod and + not mc.getArgument(0).hasValue() + } + + abstract class SweetJaysonSink extends ConstructorOrStaticMethodSink { } + + class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { + SweetJaysonDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isSweetJaysonCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + /** ServiceStack.Text.JsonSerializer */ + abstract class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } + + class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { + ServiceStackTextJsonSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextJsonSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextJsonSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod + ) and + not mc.getAnArgument().hasValue() and + not mc.getAnArgument() instanceof TypeofExpr and + this.asExpr() = mc.getAnArgument() + ) + } + } + + /** ServiceStack.Text.TypeSerializer */ + abstract class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } + + class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { + ServiceStackTextTypeSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextTypeSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextTypeSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod + ) and + not mc.getAnArgument().hasValue() and + not mc.getAnArgument() instanceof TypeofExpr and + this.asExpr() = mc.getAnArgument() + ) + } + } + + /** ServiceStack.Text.CsvSerializer */ + abstract class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } + + class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { + ServiceStackTextCsvSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextCsvSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextCsvSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod + ) and + not mc.getAnArgument().hasValue() and + not mc.getAnArgument() instanceof TypeofExpr and + this.asExpr() = mc.getAnArgument() + ) + } + } + + /** ServiceStack.Text.XmlSerializer */ + abstract class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } + + class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { + ServiceStackTextXmlSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextXmlSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextXmlSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod + ) and + not mc.getAnArgument().hasValue() and + not mc.getAnArgument() instanceof TypeofExpr and + this.asExpr() = mc.getAnArgument() ) } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 8bb6e8d2b24..bf9c74e645b 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -5,50 +5,134 @@ import csharp -/** An unsafe deserializer. */ -abstract class UnsafeDeserializer extends Callable { } - -/** An unsafe deserializer method in the `System.*` namespace. */ -class SystemDeserializer extends UnsafeDeserializer { - SystemDeserializer() { - this.hasQualifiedName("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter", - "Deserialize") +/** Unsafe deserialization calls. */ +class UnsafeDeserializerCallable extends Callable { + UnsafeDeserializerCallable() { + this instanceof BinaryFormatterDeserializeMethod or - this.hasQualifiedName("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter", - "UnsafeDeserialize") + this instanceof BinaryFormatterUnsafeDeserializeMethod or - this.hasQualifiedName("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter", - "UnsafeDeserializeMethodResponse") + this instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod or - this.hasQualifiedName("System.Runtime.Deserialization.Formatters.Soap.SoapFormatter", - "Deserialize") + this instanceof SoapFormatterDeserializeMethod or - this.hasQualifiedName("System.Web.UI.ObjectStateFormatter", "Deserialize") + this instanceof ObjectStateFormatterDeserializeMethod or - this.hasQualifiedName("System.Runtime.Serialization.NetDataContractSerializer", "Deserialize") + this instanceof NetDataContractSerializerDeserializeMethod or - this.hasQualifiedName("System.Runtime.Serialization.NetDataContractSerializer", "ReadObject") + this instanceof NetDataContractSerializerReadObjectMethod or - this.hasQualifiedName("System.Web.UI.LosFormatter", "Deserialize") + this instanceof DataContractJsonSerializerReadObjectMethod or - this.hasQualifiedName("System.Workflow.ComponentModel.Activity", "Load") + this instanceof JavaScriptSerializerClassDeserializeMethod or - this.hasQualifiedName("System.Resources.ResourceReader", "ResourceReader") + this instanceof JavaScriptSerializerClassDeserializeObjectMethod or - this.hasQualifiedName("System.Messaging", "BinaryMessageFormatter") + this instanceof XmlObjectSerializerReadObjectMethod or - this.hasQualifiedName("System.Windows.Markup.XamlReader", "Parse") + this instanceof XmlSerializerDeserializeMethod or - this.hasQualifiedName("System.Windows.Markup.XamlReader", "Load") + this instanceof DataContractSerializerReadObjectMethod or - this.hasQualifiedName("System.Windows.Markup.XamlReader", "LoadAsync") + this instanceof XmlMessageFormatterReadMethod + or + this instanceof LosFormatterDeserializeMethod + or + this instanceof FastJsonClassToObjectMethod + or + this instanceof ActivityLoadMethod + or + this instanceof ResourceReaderConstructor + or + this instanceof BinaryMessageFormatterReadMethod + or + this instanceof XamlReaderParseMethod + or + this instanceof XamlReaderLoadMethod + or + this instanceof XamlReaderLoadAsyncMethod + or + this instanceof ProxyObjectDecodeValueMethod + or + this instanceof ProxyObjectDecodeSerializedObjectMethod + or + this instanceof JaysonConverterToObjectMethod + or + this instanceof ServiceStackTextJsonSerializerDeserializeFromStringMethod + or + this instanceof ServiceStackTextJsonSerializerDeserializeFromReaderMethod + or + this instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod + or + this instanceof ServiceStackTextTypeSerializerDeserializeFromStringMethod + or + this instanceof ServiceStackTextTypeSerializerDeserializeFromReaderMethod + or + this instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod + or + this instanceof ServiceStackTextCsvSerializerDeserializeFromStringMethod + or + this instanceof ServiceStackTextCsvSerializerDeserializeFromReaderMethod + or + this instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod + or + this instanceof ServiceStackTextXmlSerializerDeserializeFromStringMethod + or + this instanceof ServiceStackTextXmlSerializerDeserializeFromReaderMethod + or + this instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod } } -/** An unsafe deserializer method in the `Microsoft.*` namespace. */ -class MicrosoftDeserializer extends UnsafeDeserializer { - MicrosoftDeserializer() { - this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject", "DecodeValue") +/** Deserializer exploitable only if user controls the expected object type. */ +class StrongTypeDeserializer extends Class { + StrongTypeDeserializer() { + this instanceof XmlSerializerClass + or + this instanceof DataContractJsonSerializerClass + or + this instanceof DataContractSerializerClass + or + this instanceof XmlMessageFormatterClass + } +} + +/** Deserializer that doesn't make strong expected type check. */ +class WeakTypeDeserializer extends Class { + WeakTypeDeserializer() { + this instanceof BinaryFormatterClass + or + this instanceof SoapFormatterClass + or + this instanceof ObjectStateFormatterClass + or + this instanceof NetDataContractSerializerClass + or + this instanceof JavaScriptSerializerClass + or + this instanceof LosFormatterClass + or + this instanceof BinaryMessageFormatterClass + or + this instanceof FastJsonClass + or + this instanceof ActivityClass + or + this instanceof XamlReaderClass + or + this instanceof ProxyObjectClass + or + this instanceof ResourceReaderClass + or + this instanceof JaysonConverterClass + or + this instanceof ServiceStackTextJsonSerializerClass + or + this instanceof ServiceStackTextTypeSerializerClass + or + this instanceof ServiceStackTextCsvSerializerClass + or + this instanceof ServiceStackTextXmlSerializerClass } } @@ -56,12 +140,415 @@ class MicrosoftDeserializer extends UnsafeDeserializer { * An unsafe deserializer method that calls any unsafe deserializer on any of * the parameters. */ -class WrapperDeserializer extends UnsafeDeserializer { +class WrapperDeserializer extends UnsafeDeserializerCallable { WrapperDeserializer() { exists(Call call | call.getEnclosingCallable() = this and call.getAnArgument() instanceof ParameterAccess and - call.getTarget() instanceof UnsafeDeserializer + call.getTarget() instanceof UnsafeDeserializerCallable ) } } + +/** BinaryFormatter */ +class BinaryFormatterClass extends Class { + BinaryFormatterClass() { + this.hasQualifiedName("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter") + } +} + +class BinaryFormatterDeserializeMethod extends Method { + BinaryFormatterDeserializeMethod() { + this.getDeclaringType() instanceof BinaryFormatterClass and + this.hasName("Deserialize") + } +} + +class BinaryFormatterUnsafeDeserializeMethod extends Method { + BinaryFormatterUnsafeDeserializeMethod() { + this.getDeclaringType() instanceof BinaryFormatterClass and + this.hasName("UnsafeDeserialize") + } +} + +class BinaryFormatterUnsafeDeserializeMethodResponseMethod extends Method { + BinaryFormatterUnsafeDeserializeMethodResponseMethod() { + this.getDeclaringType() instanceof BinaryFormatterClass and + this.hasName("UnsafeDeserializeMethodResponse") + } +} + +/** SoapFormatter */ +class SoapFormatterClass extends Class { + SoapFormatterClass() { + this.hasQualifiedName("System.Runtime.Serialization.Formatters.Soap.SoapFormatter") + } +} + +class SoapFormatterDeserializeMethod extends Method { + SoapFormatterDeserializeMethod() { + this.getDeclaringType() instanceof SoapFormatterClass and + this.hasName("Deserialize") + } +} + +/** ObjectStateFormatter */ +class ObjectStateFormatterClass extends Class { + ObjectStateFormatterClass() { this.hasQualifiedName("System.Web.UI.ObjectStateFormatter") } +} + +class ObjectStateFormatterDeserializeMethod extends Method { + ObjectStateFormatterDeserializeMethod() { + this.getDeclaringType() instanceof ObjectStateFormatterClass and + this.hasName("Deserialize") + } +} + +/** NetDataContractSerializer */ +class NetDataContractSerializerClass extends Class { + NetDataContractSerializerClass() { + this.hasQualifiedName("System.Runtime.Serialization.NetDataContractSerializer") + } +} + +class NetDataContractSerializerDeserializeMethod extends Method { + NetDataContractSerializerDeserializeMethod() { + this.getDeclaringType() instanceof NetDataContractSerializerClass and + this.hasName("Deserialize") + } +} + +class NetDataContractSerializerReadObjectMethod extends Method { + NetDataContractSerializerReadObjectMethod() { + this.getDeclaringType() instanceof NetDataContractSerializerClass and + this.hasName("ReadObject") + } +} + +/** DataContractJsonSerializer */ +class DataContractJsonSerializerClass extends Class { + DataContractJsonSerializerClass() { + this.hasQualifiedName("System.Runtime.Serialization.Json.DataContractJsonSerializer") + } +} + +class DataContractJsonSerializerReadObjectMethod extends Method { + DataContractJsonSerializerReadObjectMethod() { + this.getDeclaringType() instanceof DataContractJsonSerializerClass and + this.hasName("ReadObject") + } +} + +/** JavaScriptSerializer */ +class JavaScriptSerializerClass extends Class { + JavaScriptSerializerClass() { + this.hasQualifiedName("System.Web.Script.Serialization.JavaScriptSerializer") + } +} + +class JavaScriptSerializerClassDeserializeMethod extends Method { + JavaScriptSerializerClassDeserializeMethod() { + this.getDeclaringType() instanceof JavaScriptSerializerClass and + this.hasName("Deserialize") + } +} + +class JavaScriptSerializerClassDeserializeObjectMethod extends Method { + JavaScriptSerializerClassDeserializeObjectMethod() { + this.getDeclaringType() instanceof JavaScriptSerializerClass and + this.hasName("DeserializeObject") + } +} + +/** XmlObjectSerializer */ +class XmlObjectSerializerClass extends Class { + XmlObjectSerializerClass() { + this.hasQualifiedName("System.Runtime.Serialization.XmlObjectSerializer") + } +} + +class XmlObjectSerializerReadObjectMethod extends Method { + XmlObjectSerializerReadObjectMethod() { + this.getDeclaringType() instanceof XmlObjectSerializerClass and + this.hasName("ReadObject") + } +} + +/** XmlSerializer */ +class XmlSerializerClass extends Class { + XmlSerializerClass() { this.hasQualifiedName("System.Xml.Serialization.XmlSerializer") } +} + +class XmlSerializerDeserializeMethod extends Method { + XmlSerializerDeserializeMethod() { + this.getDeclaringType() instanceof XmlSerializerClass and + this.hasName("Deserialize") + } +} + +/** DataContractSerializer */ +class DataContractSerializerClass extends Class { + DataContractSerializerClass() { + this.hasQualifiedName("System.Runtime.Serialization.DataContractSerializer") + } +} + +class DataContractSerializerReadObjectMethod extends Method { + DataContractSerializerReadObjectMethod() { + this.getDeclaringType() instanceof DataContractSerializerClass and + this.hasName("ReadObject") + } +} + +/** XmlMessageFormatter */ +class XmlMessageFormatterClass extends Class { + XmlMessageFormatterClass() { this.hasQualifiedName("System.Messaging.XmlMessageFormatter") } +} + +class XmlMessageFormatterReadMethod extends Method { + XmlMessageFormatterReadMethod() { + this.getDeclaringType() instanceof XmlMessageFormatterClass and + this.hasName("Read") + } +} + +/** LosFormatter */ +class LosFormatterClass extends Class { + LosFormatterClass() { this.hasQualifiedName("System.Web.UI.LosFormatter") } +} + +class LosFormatterDeserializeMethod extends Method { + LosFormatterDeserializeMethod() { + this.getDeclaringType() instanceof LosFormatterClass and + this.hasName("Deserialize") + } +} + +/** fastJSON */ +class FastJsonClass extends Class { + FastJsonClass() { this.hasQualifiedName("fastJSON.JSON") } +} + +class FastJsonClassToObjectMethod extends Method { + FastJsonClassToObjectMethod() { + this.getDeclaringType() instanceof FastJsonClass and + this.hasName("ToObject") and + this.isStatic() + } +} + +/** Activity */ +class ActivityClass extends Class { + ActivityClass() { this.hasQualifiedName("System.Workflow.ComponentModel.Activity") } +} + +class ActivityLoadMethod extends Method { + ActivityLoadMethod() { + this.getDeclaringType() instanceof ActivityClass and + this.hasName("Load") + } +} + +/** ResourceReader */ +class ResourceReaderClass extends Class { + ResourceReaderClass() { this.hasQualifiedName("System.Resources.ResourceReader") } +} + +class ResourceReaderConstructor extends Constructor { + ResourceReaderConstructor() { + this.getDeclaringType() instanceof ResourceReaderClass and + this.hasName("ResourceReader") + } +} + +/** BinaryMessageFormatter */ +class BinaryMessageFormatterClass extends Class { + BinaryMessageFormatterClass() { this.hasQualifiedName("System.Messaging.BinaryMessageFormatter") } +} + +class BinaryMessageFormatterReadMethod extends Method { + BinaryMessageFormatterReadMethod() { + this.getDeclaringType() instanceof BinaryMessageFormatterClass and + this.hasName("Read") + } +} + +/** XamlReader */ +class XamlReaderClass extends Class { + XamlReaderClass() { this.hasQualifiedName("System.Windows.Markup.XamlReader") } +} + +class XamlReaderParseMethod extends Method { + XamlReaderParseMethod() { + this.getDeclaringType() instanceof XamlReaderClass and + this.hasName("Parse") and + this.isStatic() + } +} + +class XamlReaderLoadMethod extends Method { + XamlReaderLoadMethod() { + this.getDeclaringType() instanceof XamlReaderClass and + this.hasName("Load") and + this.isStatic() + } +} + +class XamlReaderLoadAsyncMethod extends Method { + XamlReaderLoadAsyncMethod() { + this.getDeclaringType() instanceof XamlReaderClass and + this.hasName("LoadAsync") + } +} + +/** ProxyObject */ +class ProxyObjectClass extends Class { + ProxyObjectClass() { this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject") } +} + +class ProxyObjectDecodeValueMethod extends Method { + ProxyObjectDecodeValueMethod() { + this.getDeclaringType() instanceof ProxyObjectClass and + this.hasName("DecodeValue") + } +} + +class ProxyObjectDecodeSerializedObjectMethod extends Method { + ProxyObjectDecodeSerializedObjectMethod() { + this.getDeclaringType() instanceof ProxyObjectClass and + this.hasName("DecodeSerializedObject") + } +} + +/** SweetJayson */ +class JaysonConverterClass extends Class { + JaysonConverterClass() { this.hasQualifiedName("Sweet.Jayson.JaysonConverter") } +} + +class JaysonConverterToObjectMethod extends Method { + JaysonConverterToObjectMethod() { + this.getDeclaringType() instanceof JaysonConverterClass and + this.hasName("ToObject") and + this.isStatic() + } +} + +/** ServiceStack.Text.JsonSerializer */ +class ServiceStackTextJsonSerializerClass extends Class { + ServiceStackTextJsonSerializerClass() { + this.hasQualifiedName("ServiceStack.Text.JsonSerializer") + } +} + +class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method { + ServiceStackTextJsonSerializerDeserializeFromStringMethod() { + this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and + this.hasName("DeserializeFromString") and + this.isStatic() + } +} + +class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method { + ServiceStackTextJsonSerializerDeserializeFromReaderMethod() { + this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and + this.hasName("DeserializeFromReader") and + this.isStatic() + } +} + +class ServiceStackTextJsonSerializerDeserializeFromStreamMethod extends Method { + ServiceStackTextJsonSerializerDeserializeFromStreamMethod() { + this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and + this.hasName("DeserializeFromStream") and + this.isStatic() + } +} + +/** ServiceStack.Text.TypeSerializer */ +class ServiceStackTextTypeSerializerClass extends Class { + ServiceStackTextTypeSerializerClass() { + this.hasQualifiedName("ServiceStack.Text.TypeSerializer") + } +} + +class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method { + ServiceStackTextTypeSerializerDeserializeFromStringMethod() { + this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and + this.hasName("DeserializeFromString") and + this.isStatic() + } +} + +class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method { + ServiceStackTextTypeSerializerDeserializeFromReaderMethod() { + this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and + this.hasName("DeserializeFromReader") and + this.isStatic() + } +} + +class ServiceStackTextTypeSerializerDeserializeFromStreamMethod extends Method { + ServiceStackTextTypeSerializerDeserializeFromStreamMethod() { + this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and + this.hasName("DeserializeFromStream") and + this.isStatic() + } +} + +/** ServiceStack.Text.CsvSerializer */ +class ServiceStackTextCsvSerializerClass extends Class { + ServiceStackTextCsvSerializerClass() { this.hasQualifiedName("ServiceStack.Text.CsvSerializer") } +} + +class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method { + ServiceStackTextCsvSerializerDeserializeFromStringMethod() { + this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and + this.hasName("DeserializeFromString") and + this.isStatic() + } +} + +class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method { + ServiceStackTextCsvSerializerDeserializeFromReaderMethod() { + this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and + this.hasName("DeserializeFromReader") and + this.isStatic() + } +} + +class ServiceStackTextCsvSerializerDeserializeFromStreamMethod extends Method { + ServiceStackTextCsvSerializerDeserializeFromStreamMethod() { + this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and + this.hasName("DeserializeFromStream") and + this.isStatic() + } +} + +/** ServiceStack.Text.XmlSerializer */ +class ServiceStackTextXmlSerializerClass extends Class { + ServiceStackTextXmlSerializerClass() { this.hasQualifiedName("ServiceStack.Text.XmlSerializer") } +} + +class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method { + ServiceStackTextXmlSerializerDeserializeFromStringMethod() { + this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and + this.hasName("DeserializeFromString") and + this.isStatic() + } +} + +class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method { + ServiceStackTextXmlSerializerDeserializeFromReaderMethod() { + this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and + this.hasName("DeserializeFromReader") and + this.isStatic() + } +} + +class ServiceStackTextXmlSerializerDeserializeFromStreamMethod extends Method { + ServiceStackTextXmlSerializerDeserializeFromStreamMethod() { + this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and + this.hasName("DeserializeFromStream") and + this.isStatic() + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs new file mode 100644 index 00000000000..1170a37ad3b --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs @@ -0,0 +1,12 @@ +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; + +class BadBinaryFormatter +{ + public static object Deserialize(Stream s) + { + var ds = new BinaryFormatter(); + // BAD + return ds.Deserialize(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs new file mode 100644 index 00000000000..1256428176c --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization.Json; +using System.IO; +using System; + +class BadDataContractJsonSerializer +{ + public static object Deserialize(Type type, Stream s) + { + var ds = new DataContractJsonSerializer(type); + // BAD + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerGood.cs new file mode 100644 index 00000000000..92adf51cfb6 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerGood.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization.Json; +using System.IO; +using System; + +class GoodDataContractJsonSerializer +{ + public static object Deserialize(Stream s) + { + // Good: type is hardcoded + var ds = new DataContractJsonSerializer(typeof(GoodDataContractJsonSerializer)); + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs new file mode 100644 index 00000000000..35cff0b45f1 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; +using System.IO; +using System; + +class BadDataContractSerializer +{ + public static object Deserialize(Type type, Stream s) + { + var ds = new DataContractSerializer(type); + // BAD + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerGood.cs new file mode 100644 index 00000000000..0e2a6f10f12 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerGood.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; +using System.IO; +using System; + +class GoodDataContractSerializer +{ + public static object Deserialize(Stream s) + { + // Good: type is hardcoded + var ds = new DataContractSerializer(typeof(GoodDataContractSerializer)); + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs index bd796aa9f51..34881f62b07 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs +// semmle-extractor-options: /r:System.Private.Xml.dll /r:System.Xml.ReaderWriter.dll /r:System.Private.DataContractSerialization.dll /r:System.Runtime.Serialization.Formatters.dll /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs new file mode 100644 index 00000000000..2da5dc1aa6a --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs @@ -0,0 +1,17 @@ +using System.Resources; +using System.IO; +using System; + +class BadResourceReader +{ + public static void Deserialize(Stream s) + { + var ds = new ResourceReader(s); + // BAD + var dict = ds.GetEnumerator(); + while (dict.MoveNext()) + Console.WriteLine(" {0}: '{1}' (Type {2})", + dict.Key, dict.Value, dict.Value.GetType().Name); + ds.Close(); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.expected b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.expected index 6edb1f62902..9a26799dc07 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.expected @@ -1 +1,7 @@ +| BinaryFormatterBad.cs:10:16:10:32 | call to method Deserialize | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +| DataContractJsonSerializerBad.cs:11:16:11:31 | call to method ReadObject | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +| DataContractSerializerBad.cs:11:16:11:31 | call to method ReadObject | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +| ResourceReaderBad.cs:9:18:9:38 | object creation of type ResourceReader | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | | UnsafeDeserializationBad.cs:9:16:9:38 | call to method DeserializeObject | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +| XmlObjectSerializerBad.cs:11:16:11:31 | call to method ReadObject | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | +| XmlSerializerBad.cs:11:16:11:32 | call to method Deserialize | Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source. | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs new file mode 100644 index 00000000000..4096934da0b --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; +using System.IO; +using System; + +class BadXmlObjectSerializer +{ + public static object Deserialize(Type type, Stream s) + { + XmlObjectSerializer ds = new DataContractSerializer(type); + // BAD + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerGood.cs new file mode 100644 index 00000000000..bde02294f1d --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerGood.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; +using System.IO; +using System; + +class GoodXmlObjectSerializer +{ + public static object Deserialize(Stream s) + { + // Good: type is hardcoded + XmlObjectSerializer ds = new DataContractSerializer(typeof(GoodXmlObjectSerializer)); + return ds.ReadObject(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs new file mode 100644 index 00000000000..4d32bae9c08 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; +using System.IO; +using System; + +class BadXmlSerializer +{ + public static object Deserialize(Type type, Stream s) + { + var ds = new XmlSerializer(type); + // BAD + return ds.Deserialize(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerGood.cs new file mode 100644 index 00000000000..f947729cdd2 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerGood.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; +using System.IO; +using System; + +class GoodXmlSerializer +{ + public static object Deserialize(Stream s) + { + // Good: type is hardcoded + var ds = new XmlSerializer(typeof(GoodXmlSerializer)); + return ds.Deserialize(s); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs new file mode 100644 index 00000000000..73c6c35413b --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs @@ -0,0 +1,14 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; +using System.Text; + +class BadBinaryFormatter +{ + public static object Deserialize(TextBox textBox) + { + var ds = new BinaryFormatter(); + // BAD + return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(textBox.Text))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputGood.cs new file mode 100644 index 00000000000..f0cf286ad9b --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputGood.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; +using System.Text; + +class GoodBinaryFormatter +{ + public static object Deserialize() + { + var ds = new BinaryFormatter(); + // GOOD + return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs new file mode 100644 index 00000000000..2d3efe3ae26 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs @@ -0,0 +1,15 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization.Json; +using System.IO; +using System.Text; +using System; + +class BadDataContractJsonSerializer +{ + public static object Deserialize(TextBox type, TextBox data) + { + var ds = new DataContractJsonSerializer(Type.GetType(type.Text)); + // BAD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputGood.cs new file mode 100644 index 00000000000..c80a6c66825 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputGood.cs @@ -0,0 +1,22 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization.Json; +using System.IO; +using System.Text; +using System; + +class GoodDataContractJsonSerializer +{ + public static object Deserialize1(TextBox data) + { + // GOOD + var ds = new DataContractJsonSerializer(typeof(GoodDataContractJsonSerializer)); + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } + + public static object Deserialize2(TextBox type) + { + var ds = new DataContractJsonSerializer(Type.GetType(type.Text)); + // GOOD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs new file mode 100644 index 00000000000..f4f266ed3e0 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs @@ -0,0 +1,15 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization; +using System.IO; +using System.Text; +using System; + +class BadDataContractSerializer +{ + public static object Deserialize(TextBox type, TextBox data) + { + var ds = new DataContractSerializer(Type.GetType(type.Text)); + // BAD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputGood.cs new file mode 100644 index 00000000000..e27ee726f21 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputGood.cs @@ -0,0 +1,22 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization; +using System.IO; +using System.Text; +using System; + +class GoodDataContractSerializer +{ + public static object Deserialize1(TextBox data) + { + // GOOD + var ds = new DataContractSerializer(typeof(GoodDataContractSerializer)); + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } + + public static object Deserialize2(TextBox type) + { + var ds = new DataContractSerializer(Type.GetType(type.Text)); + // GOOD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs index bd796aa9f51..34881f62b07 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs +// semmle-extractor-options: /r:System.Private.Xml.dll /r:System.Xml.ReaderWriter.dll /r:System.Private.DataContractSerialization.dll /r:System.Runtime.Serialization.Formatters.dll /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs new file mode 100644 index 00000000000..cd5468afc2d --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs @@ -0,0 +1,19 @@ +using System.Web.UI.WebControls; +using System.Resources; +using System.IO; +using System.Text; +using System; + +class BadResourceReader +{ + public static void Deserialize(TextBox data) + { + var ds = new ResourceReader(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + // BAD + var dict = ds.GetEnumerator(); + while (dict.MoveNext()) + Console.WriteLine(" {0}: '{1}' (Type {2})", + dict.Key, dict.Value, dict.Value.GetType().Name); + ds.Close(); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputGood.cs new file mode 100644 index 00000000000..4120613e007 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputGood.cs @@ -0,0 +1,19 @@ +using System.Web.UI.WebControls; +using System.Resources; +using System.IO; +using System.Text; +using System; + +class GoodResourceReader +{ + public static void Deserialize(TextBox data) + { + // GOOD + var ds = new ResourceReader(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + var dict = ds.GetEnumerator(); + while (dict.MoveNext()) + Console.WriteLine(" {0}: '{1}' (Type {2})", + dict.Key, dict.Value, dict.Value.GetType().Name); + ds.Close(); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected index ee356f9f1d0..57d849a34b0 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected @@ -1,7 +1,147 @@ edges +| BinaryFormatterUntrustedInputBad.cs:10:18:10:38 | object creation of type BinaryFormatter : BinaryFormatter | BinaryFormatterUntrustedInputBad.cs:12:16:12:17 | access to local variable ds | +| BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | +| BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | +| BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | +| BinaryFormatterUntrustedInputGood.cs:9:18:9:38 | object creation of type BinaryFormatter : BinaryFormatter | BinaryFormatterUntrustedInputGood.cs:11:16:11:17 | access to local variable ds | +| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:65 | access to parameter type : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | +| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | +| DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | +| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | +| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| DataContractJsonSerializerUntrustedInputGood.cs:12:18:12:87 | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | DataContractJsonSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | +| DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | +| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | +| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:65 | access to parameter type : TextBox | DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | +| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | DataContractJsonSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | +| DataContractSerializerUntrustedInputBad.cs:11:58:11:61 | access to parameter type : TextBox | DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | +| DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | DataContractSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | +| DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | +| DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | +| DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| DataContractSerializerUntrustedInputGood.cs:12:18:12:79 | object creation of type DataContractSerializer : DataContractSerializer | DataContractSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | +| DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | +| DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | +| DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| DataContractSerializerUntrustedInputGood.cs:18:58:18:61 | access to parameter type : TextBox | DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | +| DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | DataContractSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | +| ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | +| ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | +| ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | +| UnsafeDeserializationUntrustedInputBad.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | UnsafeDeserializationUntrustedInputBad.cs:10:16:10:17 | access to local variable sr | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | +| UnsafeDeserializationUntrustedInputGood.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | UnsafeDeserializationUntrustedInputGood.cs:10:16:10:17 | access to local variable sr | +| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:77 | access to parameter type : TextBox | XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | +| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | XmlObjectSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | +| XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | +| XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | +| XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| XmlObjectSerializerUntrustedInputGood.cs:12:34:12:92 | object creation of type DataContractSerializer : DataContractSerializer | XmlObjectSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | +| XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | +| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | +| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | +| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:77 | access to parameter type : TextBox | XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | +| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | XmlObjectSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | +| XmlSerializerUntrustedInputBad.cs:11:49:11:52 | access to parameter type : TextBox | XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | +| XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | +| XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | +| XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | +| XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | +| XmlSerializerUntrustedInputGood.cs:12:18:12:61 | object creation of type XmlSerializer : XmlSerializer | XmlSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | +| XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | +| XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | +| XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | +| XmlSerializerUntrustedInputGood.cs:18:49:18:52 | access to parameter type : TextBox | XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | +| XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | XmlSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | nodes +| BinaryFormatterUntrustedInputBad.cs:10:18:10:38 | object creation of type BinaryFormatter : BinaryFormatter | semmle.label | object creation of type BinaryFormatter : BinaryFormatter | +| BinaryFormatterUntrustedInputBad.cs:12:16:12:17 | access to local variable ds | semmle.label | access to local variable ds | +| BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox | +| BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | semmle.label | access to property Text : String | +| BinaryFormatterUntrustedInputGood.cs:9:18:9:38 | object creation of type BinaryFormatter : BinaryFormatter | semmle.label | object creation of type BinaryFormatter : BinaryFormatter | +| BinaryFormatterUntrustedInputGood.cs:11:16:11:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:65 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractJsonSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractJsonSerializerUntrustedInputGood.cs:12:18:12:87 | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | semmle.label | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | +| DataContractJsonSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:65 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractJsonSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractSerializerUntrustedInputBad.cs:11:58:11:61 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractSerializerUntrustedInputGood.cs:12:18:12:79 | object creation of type DataContractSerializer : DataContractSerializer | semmle.label | object creation of type DataContractSerializer : DataContractSerializer | +| DataContractSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractSerializerUntrustedInputGood.cs:18:58:18:61 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | semmle.label | access to property Text : String | +| DataContractSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | +| ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | semmle.label | access to property Text : String | +| UnsafeDeserializationUntrustedInputBad.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | semmle.label | object creation of type JavaScriptSerializer : JavaScriptSerializer | +| UnsafeDeserializationUntrustedInputBad.cs:10:16:10:17 | access to local variable sr | semmle.label | access to local variable sr | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | semmle.label | access to property Text | +| UnsafeDeserializationUntrustedInputGood.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | semmle.label | object creation of type JavaScriptSerializer : JavaScriptSerializer | +| UnsafeDeserializationUntrustedInputGood.cs:10:16:10:17 | access to local variable sr | semmle.label | access to local variable sr | +| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:77 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | semmle.label | access to property Text : String | +| XmlObjectSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| XmlObjectSerializerUntrustedInputGood.cs:12:34:12:92 | object creation of type DataContractSerializer : DataContractSerializer | semmle.label | object creation of type DataContractSerializer : DataContractSerializer | +| XmlObjectSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | +| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:77 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | semmle.label | access to property Text : String | +| XmlObjectSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | +| XmlSerializerUntrustedInputBad.cs:11:49:11:52 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | semmle.label | access to property Text : String | +| XmlSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | +| XmlSerializerUntrustedInputGood.cs:12:18:12:61 | object creation of type XmlSerializer : XmlSerializer | semmle.label | object creation of type XmlSerializer : XmlSerializer | +| XmlSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | +| XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | +| XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | +| XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | +| XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | +| XmlSerializerUntrustedInputGood.cs:18:49:18:52 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | +| XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | semmle.label | access to property Text : String | +| XmlSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | #select -| UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | $@ flows to unsafe deserializer. | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox | User-provided data | +| BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | User-provided data | +| DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data | +| DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data | +| ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | User-provided data | +| UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | $@ flows to unsafe deserializer. | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | User-provided data | +| XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data | +| XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | User-provided data | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs index d1e2935b218..05222245f9a 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs @@ -5,8 +5,8 @@ class Good { public static object Deserialize(TextBox textBox) { - JavaScriptSerializer sr = new JavaScriptSerializer(); + JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver()); // GOOD - return sr.DeserializeObject(textBox.Text); + return sr.DeserializeObject("hardcoded"); } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs new file mode 100644 index 00000000000..b525dd28692 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs @@ -0,0 +1,15 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization; +using System.IO; +using System.Text; +using System; + +class BadXmlObjectSerializer +{ + public static object Deserialize(TextBox type, TextBox data) + { + XmlObjectSerializer ds = new DataContractSerializer(Type.GetType(type.Text)); + // BAD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputGood.cs new file mode 100644 index 00000000000..1943f022316 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputGood.cs @@ -0,0 +1,22 @@ +using System.Web.UI.WebControls; +using System.Runtime.Serialization; +using System.IO; +using System.Text; +using System; + +class GoodXmlObjectSerializer +{ + public static object Deserialize1(TextBox data) + { + // GOOD + XmlObjectSerializer ds = new DataContractSerializer(typeof(GoodXmlObjectSerializer)); + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } + + public static object Deserialize2(TextBox type) + { + XmlObjectSerializer ds = new DataContractSerializer(Type.GetType(type.Text)); + // GOOD + return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + } +} \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs new file mode 100644 index 00000000000..f658f2a9e1a --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs @@ -0,0 +1,15 @@ +using System.Web.UI.WebControls; +using System.Xml.Serialization; +using System.IO; +using System.Text; +using System; + +class BadXmlSerializer +{ + public static object Deserialize(TextBox type, TextBox data) + { + var ds = new XmlSerializer(Type.GetType(type.Text)); + // BAD + return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputGood.cs new file mode 100644 index 00000000000..7ac7bc5def7 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputGood.cs @@ -0,0 +1,22 @@ +using System.Web.UI.WebControls; +using System.Xml.Serialization; +using System.IO; +using System.Text; +using System; + +class GoodXmlSerializer +{ + public static object Deserialize1(TextBox data) + { + // GOOD + var ds = new XmlSerializer(typeof(GoodXmlSerializer)); + return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); + } + + public static object Deserialize2(TextBox type) + { + var ds = new XmlSerializer(Type.GetType(type.Text)); + // GOOD + return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes("hardcoded"))); + } +} From 517a9202ce9a9d79dabb080b6c1d057ebf67dce9 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 17:51:17 +0200 Subject: [PATCH 002/429] PR init --- .../Security/CWE-943/NoSQLInjection.qhelp | 17 ++++++++++ .../Security/CWE-943/NoSQLInjection.ql | 20 ++++++++++++ .../experimental/semmle/python/Concepts.qll | 10 ++++++ .../semmle/python/frameworks/Stdlib.qll | 8 +++++ .../security/injection/NoSQLInjection.qll | 13 ++++++++ .../Security/CWE-943/NoSQLInjectio.qlref | 1 + .../Security/CWE-943/NoSQLInjection.expected | 0 .../Security/CWE-943/flask_mongoengine_bad.py | 30 +++++++++++++++++ .../CWE-943/flask_mongoengine_good.py | 32 +++++++++++++++++++ .../Security/CWE-943/flask_pymongo_bad.py | 18 +++++++++++ .../Security/CWE-943/flask_pymongo_good.py | 20 ++++++++++++ 11 files changed, 169 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp create mode 100644 python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql create mode 100644 python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp new file mode 100644 index 00000000000..0ca50700f2c --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql new file mode 100644 index 00000000000..7df28431dc1 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -0,0 +1,20 @@ +/** + * @name NoSQL Injection + * @description Building a NoSQL query from user-controlled sources is vulnerable to insertion of + * malicious NoSQL code by the user. + * @kind path-problem + * @problem.severity error + * @id python/nosql-injection + * @tags experimental + * security + * external/cwe/cwe-943 + */ + +import python +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +// https://ghsecuritylab.slack.com/archives/CQJU6RN49/p1617022135088100 +import semmle.python.dataflow.new.TaintTracking2 +import DataFlow::PathGraph +// from, where, select statements diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 904b7967ee8..48f9cf88e6d 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -13,3 +13,13 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks + +/** + * To-Do: + * + * NoSQLExecution: Collects functions that execute nosql queries + * getNoSQLNode - get (Sink) argument holding the query + * NoSQLEscape: Collects functions that escape nosql queries + * getNoSQLEscapeNode - get argument holding the query to-sanitize + */ +module NoSQLExecution { } diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 420caf0d73b..50ba511b880 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -9,3 +9,11 @@ private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs + +/** + * PyMongoQuery + * MongoEngineQuery + * Custom escapes + */ +private module NoSQL { } +// introduce more json libs like python\ql\src\semmle\python\frameworks\Stdlib.qll:941 diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll new file mode 100644 index 00000000000..c79e75dabca --- /dev/null +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -0,0 +1,13 @@ +import python +import experimental.semmle.python.Concepts +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.dataflow.new.RemoteFlowSources + +/** + * Create custom sink to cast in main query + * This file will hold all configs + */ +class Foo extends DataFlow::Node { + Foo() { none() } +} diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref new file mode 100644 index 00000000000..dfdfdb51de0 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-943/RegexInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py new file mode 100644 index 00000000000..1f7d4e0ec06 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -0,0 +1,30 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +import mongoengine as me +import json + +app = Flask(__name__) +db = MongoEngine(app) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + + data = Movie.objects(title=unsanitized_search) + return data.to_json() + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py new file mode 100644 index 00000000000..3f515b2ecb8 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -0,0 +1,32 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +import mongoengine as me +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) +db = MongoEngine(app) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + sanitize(unsanitized_search) + + data = Movie.objects(title=unsanitized_search) + return data.to_json() + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py new file mode 100644 index 00000000000..2fec9f0b184 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py @@ -0,0 +1,18 @@ +from flask import Flask, request +from flask_pymongo import PyMongo +import json + +app = Flask(__name__) +app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" +mongo = PyMongo(app) + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + + db_results = mongo.db.user.find({'name': unsanitized_search}) + return db_results[0].keys() + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py new file mode 100644 index 00000000000..3a0d5545ad0 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py @@ -0,0 +1,20 @@ +from flask import Flask, request +from flask_pymongo import PyMongo +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) +app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" +mongo = PyMongo(app) + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + sanitize(unsanitized_search) + + db_results = mongo.db.user.find({'name': unsanitized_search}) + return db_results[0].keys() + +# if __name__ == "__main__": +# app.run(debug=True) From aea7546cf91f955564b031d2d297f950a12ce793 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 21:13:15 +0200 Subject: [PATCH 003/429] Add Concepts --- .../experimental/semmle/python/Concepts.qll | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 48f9cf88e6d..ff418437f8a 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -14,12 +14,30 @@ private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.dataflow.new.TaintTracking private import experimental.semmle.python.Frameworks -/** - * To-Do: - * - * NoSQLExecution: Collects functions that execute nosql queries - * getNoSQLNode - get (Sink) argument holding the query - * NoSQLEscape: Collects functions that escape nosql queries - * getNoSQLEscapeNode - get argument holding the query to-sanitize - */ -module NoSQLExecution { } +module NoSQLQuery { + abstract class Range extends DataFlow::Node { + abstract DataFlow::Node getQueryNode(); + } +} + +class NoSQLQuery extends DataFlow::Node { + NoSQLQuery::Range range; + + NoSQLQuery() { this = range } + + DataFlow::Node getQueryNode() { result = range.getQueryNode() } +} + +module NoSQLSanitizer { + abstract class Range extends DataFlow::Node { + abstract DataFlow::Node getSanitizerNode(); + } +} + +class NoSQLSanitizer extends DataFlow::Node { + NoSQLSanitizer::Range range; + + NoSQLSanitizer() { this = range } + + DataFlow::Node getSanitizerNode() { result = range.getSanitizerNode() } +} From bd5ff01ebbef8e04083a7e5efb76bb18d79236c1 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 21:13:43 +0200 Subject: [PATCH 004/429] PyMongo and Mongoengine sinks --- .../semmle/python/frameworks/Stdlib.qll | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 50ba511b880..c1bb0bfcabf 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -11,9 +11,60 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs /** - * PyMongoQuery - * MongoEngineQuery + * PyMongoCall + * MongoEngineCall * Custom escapes */ -private module NoSQL { } -// introduce more json libs like python\ql\src\semmle\python\frameworks\Stdlib.qll:941 +private module NoSQL { + // doesn't work currently + private class PyMongoCall extends DataFlow::Node, NoSQLQuery::Range { + DataFlow::Node queryNode; + + PyMongoCall() { + exists(SsaVariable clientVar, CallNode findCall | + ( + clientVar.getDefinition().getImmediateDominator() = + Value::named("pymongo.MongoClient").getACall() or + clientVar.getDefinition().getImmediateDominator() = + Value::named("flask_pymongo.PyMongo").getACall() + ) and + clientVar.getAUse().getNode() = findCall.getNode().getFunc().(Attribute).getObject() and + findCall.getNode().getFunc().(Attribute).getName().matches("%find%") and + this.asCfgNode() = findCall and + queryNode.asExpr() = findCall.getArg(0).getNode() + ) + } + + override DataFlow::Node getQueryNode() { result = queryNode } + } + + // `API::moduleImport("mongoengine").getMember("Document").getASubclass*().getACall()` doesn't point + // to our sinks + private class MongoEngineCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + DataFlow::Node queryNode; + + MongoEngineCall() { + exists(DataFlow::AttrRead objectsMethod | + this.getFunction() = objectsMethod and + API::moduleImport("mongoengine").getMember("Document").getASubclass*().getACall() = + objectsMethod.getObject().getALocalSource() and + queryNode = this.getArg(0) + ) + } + + override DataFlow::Node getQueryNode() { result = queryNode } + } + + // pending: look for more Sanitizer libs + private class MongoSanitizer extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { + DataFlow::Node escapeNode; + + MongoSanitizer() { + this = + API::moduleImport("mongosanitizer").getMember("sanitizer").getMember("sanitize").getACall() and + escapeNode = this.getArg(0) + } + + override DataFlow::Node getSanitizerNode() { result = escapeNode } + } +} From d856f160c8572b1c7d3de2a41283acc242f76599 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 21:14:21 +0200 Subject: [PATCH 005/429] Adapt query configs and custom classes --- .../security/injection/NoSQLInjection.qll | 107 +++++++++++++++++- 1 file changed, 101 insertions(+), 6 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index c79e75dabca..e34d223a2de 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -3,11 +3,106 @@ import experimental.semmle.python.Concepts import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.ApiGraphs -/** - * Create custom sink to cast in main query - * This file will hold all configs - */ -class Foo extends DataFlow::Node { - Foo() { none() } +// custom no-Concepts classes +class JsonLoadsCall extends DataFlow::CallCfgNode { + DataFlow::Node loadNode; + + JsonLoadsCall() { this = API::moduleImport("json").getMember("loads").getACall() } + + DataFlow::Node getLoadNode() { result = this.getArg(0) } +} + +class XmlToDictParseCall extends DataFlow::CallCfgNode { + DataFlow::Node parseNode; + + XmlToDictParseCall() { this = API::moduleImport("xmltodict").getMember("parse").getACall() } + + DataFlow::Node getParseNode() { result = this.getArg(0) } +} + +class UltraJsonLoadsCall extends DataFlow::CallCfgNode { + DataFlow::Node loadNode; + + UltraJsonLoadsCall() { this = API::moduleImport("ujson").getMember("loads").getACall() } + + DataFlow::Node getLoadNode() { result = this.getArg(0) } +} + +// configs +class XmlToDictParseConfig extends TaintTracking::Configuration { + XmlToDictParseConfig() { this = "XmlToDictParseConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = any(XmlToDictParseCall xmlToDictParse).getParseNode() + } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + } +} + +// Must be passed through json.loads(here) since otherwise it would be a string instead of a dict. +class JsonLoadsConfig extends TaintTracking::Configuration { + JsonLoadsConfig() { this = "JsonLoadsConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = any(JsonLoadsCall jsonLoads).getLoadNode() + } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + } +} + +// Must be passed through json.loads(here) since otherwise it would be a string instead of a dict. +class UltraJsonLoadsConfig extends TaintTracking::Configuration { + UltraJsonLoadsConfig() { this = "UltraJsonLoadsConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink = any(UltraJsonLoadsCall ultraCall).getLoadNode() + } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + } +} + +// This predicate should handle args passed to json, xmltodict, ujson, etc. +class ObjectBuilderMethodArg extends DataFlow::Node { + ObjectBuilderMethodArg() { + this in [ + any(JsonLoadsCall jsonLoads).getLoadNode(), + any(XmlToDictParseCall xmlToDictParse).getParseNode(), + any(UltraJsonLoadsCall ultraCall).getLoadNode() + ] + } +} + +// I don't think this is possible, we should do something like this in the main query: +/** + * config1.hasFlowPath(source, sink) or config2.hasFlowPath(source, sink) or config3.hasFlowPath(source, sink) + * where configs are variables declared from the configs in the list below. + * + * class ObjectBuilderMethod extends DataFlow::Node { + * ObjectBuilderMethod() { this in [JsonLoadsConfig, XmlToDictParseConfig, UltraJsonLoadsConfig] } + *} + */ +class NoSQLInjection extends TaintTracking::Configuration { + NoSQLInjection() { this = "NoSQLInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof ObjectBuilderMethodArg } // Will be JsonLoadsArg + + override predicate isSink(DataFlow::Node sink) { sink instanceof MongoSinks } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + } } From 4579132f22a3d5e73962ad3e5c7ac18cb1b416e1 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 21:14:33 +0200 Subject: [PATCH 006/429] Add left tests --- .../Security/CWE-943/pymongo_bad.py | 17 +++++++++++++++++ .../Security/CWE-943/pymongo_good.py | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py new file mode 100644 index 00000000000..46594af9766 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py @@ -0,0 +1,17 @@ +from flask import Flask, request +from pymongo import MongoClient +import json + +app = Flask(__name__) +client = MongoClient() + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + + db_results = client.db.collection.find_one({'data': unsanitized_search}) + return db_results[0].keys() + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py new file mode 100644 index 00000000000..58b1cd27c7e --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py @@ -0,0 +1,19 @@ +from flask import Flask, request +from pymongo import MongoClient +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) +client = MongoClient() + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + sanitize(unsanitized_search) + + db_results = client.db.collection.find_one({'data': unsanitized_search}) + return db_results[0].keys() + +# if __name__ == "__main__": +# app.run(debug=True) From ccd57bea7a25976ad1ae46ce42b5ffb007986a37 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 30 Mar 2021 21:17:11 +0200 Subject: [PATCH 007/429] Fix imports --- .../ql/src/experimental/Security/CWE-943/NoSQLInjection.ql | 6 +----- .../semmle/python/security/injection/NoSQLInjection.qll | 2 ++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index 7df28431dc1..4fa46ce3ff7 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -11,10 +11,6 @@ */ import python -import semmle.python.dataflow.new.RemoteFlowSources -import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.TaintTracking -// https://ghsecuritylab.slack.com/archives/CQJU6RN49/p1617022135088100 -import semmle.python.dataflow.new.TaintTracking2 +import experimental.semmle.python.security.injection.NoSQLInjection import DataFlow::PathGraph // from, where, select statements diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index e34d223a2de..350b1e9273f 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -2,6 +2,8 @@ import python import experimental.semmle.python.Concepts import semmle.python.dataflow.new.DataFlow import semmle.python.dataflow.new.TaintTracking +// https://ghsecuritylab.slack.com/archives/CQJU6RN49/p1617022135088100 +import semmle.python.dataflow.new.TaintTracking2 import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.ApiGraphs From 94234b8b0240d4c5cf13658aeb82318fa991a786 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:22:30 +0300 Subject: [PATCH 008/429] Rename ObjectMethodSink to InstanceMethodSink --- .../CWE-502/UnsafeDeserialization.ql | 2 +- .../dataflow/UnsafeDeserialization.qll | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index dedf21a1859..24960b9dc52 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -13,7 +13,7 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization -from Call deserializeCall, ObjectMethodSink sink +from Call deserializeCall, InstanceMethodSink sink where deserializeCall.getAnArgument() = sink.asExpr() and not exists( diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index f63d0ef7021..78e41ddc235 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -16,7 +16,7 @@ module UnsafeDeserialization { /** * A data flow sink for unsafe deserialization vulnerabilities. */ - abstract class ObjectMethodSink extends DataFlow::Node { } + abstract class InstanceMethodSink extends DataFlow::Node { } /** * A data flow sink for unsafe deserialization vulnerabilities. @@ -36,7 +36,7 @@ module UnsafeDeserialization { override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMethodSink } + override predicate isSink(DataFlow::Node sink) { sink instanceof InstanceMethodSink } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } @@ -133,7 +133,7 @@ module UnsafeDeserialization { ) } - abstract class BinaryFormatterSink extends ObjectMethodSink { } + abstract class BinaryFormatterSink extends InstanceMethodSink { } class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { BinaryFormatterDeserializeMethodSink() { @@ -151,7 +151,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class SoapFormatterSink extends ObjectMethodSink { } + abstract class SoapFormatterSink extends InstanceMethodSink { } class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { SoapFormatterDeserializeMethodSink() { @@ -169,7 +169,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class ObjectStateFormatterSink extends ObjectMethodSink { } + abstract class ObjectStateFormatterSink extends InstanceMethodSink { } class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { ObjectStateFormatterDeserializeMethodSink() { @@ -192,7 +192,7 @@ module UnsafeDeserialization { ) } - abstract class NetDataContractSerializerSink extends ObjectMethodSink { } + abstract class NetDataContractSerializerSink extends InstanceMethodSink { } class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { NetDataContractSerializerDeserializeMethodSink() { @@ -210,7 +210,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class DataContractJsonSerializerSink extends ObjectMethodSink { } + abstract class DataContractJsonSerializerSink extends InstanceMethodSink { } class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { DataContractJsonSerializerDeserializeMethodSink() { @@ -253,7 +253,7 @@ module UnsafeDeserialization { ) } - abstract class JavaScriptSerializerSink extends ObjectMethodSink { } + abstract class JavaScriptSerializerSink extends InstanceMethodSink { } class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { JavaScriptSerializerDeserializeMethodSink() { @@ -291,7 +291,7 @@ module UnsafeDeserialization { not mc.targetIsLocalInstance() } - abstract class XmlObjectSerializerSink extends ObjectMethodSink { } + abstract class XmlObjectSerializerSink extends InstanceMethodSink { } class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { XmlObjectSerializerDeserializeMethodSink() { @@ -333,7 +333,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class XmlSerializerSink extends ObjectMethodSink { } + abstract class XmlSerializerSink extends InstanceMethodSink { } class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { XmlSerializerDeserializeMethodSink() { @@ -374,7 +374,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class DataContractSerializerSink extends ObjectMethodSink { } + abstract class DataContractSerializerSink extends InstanceMethodSink { } class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { DataContractSerializerDeserializeMethodSink() { @@ -412,7 +412,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class XmlMessageFormatterSink extends ObjectMethodSink { } + abstract class XmlMessageFormatterSink extends InstanceMethodSink { } class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { XmlMessageFormatterDeserializeMethodSink() { @@ -450,7 +450,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class LosFormatterSink extends ObjectMethodSink { } + abstract class LosFormatterSink extends InstanceMethodSink { } class LosFormatterDeserializeMethodSink extends LosFormatterSink { LosFormatterDeserializeMethodSink() { @@ -486,7 +486,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class ActivitySink extends ObjectMethodSink { } + abstract class ActivitySink extends InstanceMethodSink { } class ActivityDeserializeMethodSink extends ActivitySink { ActivityDeserializeMethodSink() { @@ -522,7 +522,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class BinaryMessageFormatterSink extends ObjectMethodSink { } + abstract class BinaryMessageFormatterSink extends InstanceMethodSink { } class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { BinaryMessageFormatterDeserializeMethodSink() { @@ -568,7 +568,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class ProxyObjectSink extends ObjectMethodSink { } + abstract class ProxyObjectSink extends InstanceMethodSink { } class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { ProxyObjectDeserializeMethodSink() { From 8bb3be26777bc2845f0128601dcb223b69e2e924 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:31:14 +0300 Subject: [PATCH 009/429] Fix comment --- .../code/csharp/security/dataflow/UnsafeDeserialization.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 78e41ddc235..f1486f14f77 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -14,12 +14,12 @@ module UnsafeDeserialization { abstract class Source extends DataFlow::Node { } /** - * A data flow sink for unsafe deserialization vulnerabilities. + * A data flow sink for unsafe deserialization vulnerabilities to an instance method. */ abstract class InstanceMethodSink extends DataFlow::Node { } /** - * A data flow sink for unsafe deserialization vulnerabilities. + * A data flow sink for unsafe deserialization vulnerabilities to a static method or constructor call. */ abstract class ConstructorOrStaticMethodSink extends DataFlow::Node { } From 7cbbd6cc895fa02111cde20b3cda33052f7df995 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:35:54 +0300 Subject: [PATCH 010/429] Simplify query --- .../ql/src/Security Features/CWE-502/UnsafeDeserialization.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 24960b9dc52..61e1a687fea 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -21,7 +21,7 @@ where SafeConstructorTrackingConfig constructorTracking | constructorTracking.hasFlowPath(constructor, usage) and - usage.getNode().asExpr().getParent() = sink.asExpr().getParent() + usage.getNode().asExpr().getParent() = deserializeCall ) or exists(ConstructorOrStaticMethodSink sink2 | deserializeCall.getAnArgument() = sink2.asExpr()) From aa9d84854f5cc5f01b71a3e1df0ebfd1204e6867 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:42:52 +0300 Subject: [PATCH 011/429] Rename taint tracking variables --- .../Security Features/CWE-502/UnsafeDeserialization.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 61e1a687fea..1208258a22a 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -17,11 +17,11 @@ from Call deserializeCall, InstanceMethodSink sink where deserializeCall.getAnArgument() = sink.asExpr() and not exists( - DataFlow::PathNode constructor, DataFlow::PathNode usage, - SafeConstructorTrackingConfig constructorTracking + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, + DataFlow::PathNode safeTypeUsage | - constructorTracking.hasFlowPath(constructor, usage) and - usage.getNode().asExpr().getParent() = deserializeCall + safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and + safeTypeUsage.getNode().asExpr().getParent() = deserializeCall ) or exists(ConstructorOrStaticMethodSink sink2 | deserializeCall.getAnArgument() = sink2.asExpr()) From f8867e40a7ab089d0ad631366abcddcef18f56f9 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:49:17 +0300 Subject: [PATCH 012/429] Rename deserializeCall to deserializeCallArg --- .../UnsafeDeserializationUntrustedInput.ql | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 0932517acce..de75bf08807 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -26,10 +26,10 @@ class LocalSource extends Source { from TaintToObjectMethodTrackingConfig taintTracking, DataFlow::PathNode userInput, - DataFlow::PathNode deserializeCall + DataFlow::PathNode deserializeCallArg where // all flows from user input to deserialization with weak and strong type serializers - taintTracking.hasFlowPath(userInput, deserializeCall) and + taintTracking.hasFlowPath(userInput, deserializeCallArg) and // intersect with strong types, but user controlled or weak types deserialization usages ( exists( @@ -37,7 +37,8 @@ where WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking | weakTypeDeserializerTracking.hasFlowPath(weakTypeCreation, weakTypeUsage) and - weakTypeUsage.getNode().asExpr().getParent() = deserializeCall.getNode().asExpr().getParent() + weakTypeUsage.getNode().asExpr().getParent() = + deserializeCallArg.getNode().asExpr().getParent() ) or exists( @@ -46,7 +47,7 @@ where | userControlledTypeTracking.hasFlowPath(userInput2, taintedTypeUsage) and taintedTypeUsage.getNode().asExpr().getParent() = - deserializeCall.getNode().asExpr().getParent() + deserializeCallArg.getNode().asExpr().getParent() ) ) and // exclude deserialization flows with safe instances (i.e. JavaScriptSerializer without resolver) @@ -55,12 +56,12 @@ where DataFlow::PathNode safeTypeUsage | safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and - safeTypeUsage.getNode().asExpr().getParent() = deserializeCall.getNode().asExpr().getParent() + safeTypeUsage.getNode().asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() ) or // no type check needed - straightforward taint -> sink exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 | - taintTracking2.hasFlowPath(userInput, deserializeCall) + taintTracking2.hasFlowPath(userInput, deserializeCallArg) ) -select deserializeCall, userInput, deserializeCall, "$@ flows to unsafe deserializer.", userInput, - "User-provided data" +select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.", + userInput, "User-provided data" From 13080703b9c434a017c7b46e8d75af705b5f7e16 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:59:19 +0300 Subject: [PATCH 013/429] Make query symmetric --- .../CWE-502/UnsafeDeserialization.ql | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 1208258a22a..17438230099 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -13,17 +13,21 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization -from Call deserializeCall, InstanceMethodSink sink +from Call deserializeCall, DataFlow::Node sink where deserializeCall.getAnArgument() = sink.asExpr() and - not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, - DataFlow::PathNode safeTypeUsage - | - safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and - safeTypeUsage.getNode().asExpr().getParent() = deserializeCall + ( + sink instanceof InstanceMethodSink and + not exists( + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, + DataFlow::PathNode safeTypeUsage + | + safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and + safeTypeUsage.getNode().asExpr().getParent() = deserializeCall + ) + or + sink instanceof ConstructorOrStaticMethodSink and + deserializeCall.getAnArgument() = sink.asExpr() ) - or - exists(ConstructorOrStaticMethodSink sink2 | deserializeCall.getAnArgument() = sink2.asExpr()) select deserializeCall, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." From 01f9d4a1b099a5e42e06aac682cfbbebc13f08fb Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 15:50:45 +0200 Subject: [PATCH 014/429] Fix MongoEngine Sink --- .../semmle/python/frameworks/Stdlib.qll | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index c1bb0bfcabf..e0ad2a4ec4d 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -38,18 +38,17 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = queryNode } } - // `API::moduleImport("mongoengine").getMember("Document").getASubclass*().getACall()` doesn't point - // to our sinks private class MongoEngineCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { DataFlow::Node queryNode; MongoEngineCall() { - exists(DataFlow::AttrRead objectsMethod | - this.getFunction() = objectsMethod and - API::moduleImport("mongoengine").getMember("Document").getASubclass*().getACall() = - objectsMethod.getObject().getALocalSource() and - queryNode = this.getArg(0) - ) + this = + API::moduleImport("mongoengine") + .getMember("Document") + .getASubclass() + .getMember("objects") + .getACall() and + queryNode = this.getArg(0) } override DataFlow::Node getQueryNode() { result = queryNode } From 7a4dc46341bf98c67c3210e5eb2afa7177379755 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 17:50:05 +0200 Subject: [PATCH 015/429] Fix Sinks --- .../semmle/python/frameworks/Stdlib.qll | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index e0ad2a4ec4d..fb2015939c9 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -10,60 +10,65 @@ private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs -/** - * PyMongoCall - * MongoEngineCall - * Custom escapes - */ private module NoSQL { - // doesn't work currently - private class PyMongoCall extends DataFlow::Node, NoSQLQuery::Range { - DataFlow::Node queryNode; + // more methods? + private class PyMongoMethods extends string { + PyMongoMethods() { this in ["find_one"] } + } + private class PyMongoCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { PyMongoCall() { - exists(SsaVariable clientVar, CallNode findCall | - ( - clientVar.getDefinition().getImmediateDominator() = - Value::named("pymongo.MongoClient").getACall() or - clientVar.getDefinition().getImmediateDominator() = - Value::named("flask_pymongo.PyMongo").getACall() - ) and - clientVar.getAUse().getNode() = findCall.getNode().getFunc().(Attribute).getObject() and - findCall.getNode().getFunc().(Attribute).getName().matches("%find%") and - this.asCfgNode() = findCall and - queryNode.asExpr() = findCall.getArg(0).getNode() - ) + this = + API::moduleImport("pymongo") + .getMember("MongoClient") + .getReturn() + .getAMember*() + .getMember(any(PyMongoMethods pyMongoM)) + .getACall() } - override DataFlow::Node getQueryNode() { result = queryNode } + override DataFlow::Node getQueryNode() { result = this.getArg(0) } + } + + // more methods? + private class PyMongoFlaskMethods extends string { + PyMongoFlaskMethods() { this in ["find"] } + } + + private class PyMongoFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + PyMongoFlaskCall() { + this = + API::moduleImport("flask_pymongo") + .getMember("PyMongo") + .getReturn() + .getAMember*() + .getMember(any(PyMongoFlaskMethods pyMongoFlaskM)) + .getACall() + } + + override DataFlow::Node getQueryNode() { result = this.getArg(0) } } private class MongoEngineCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - DataFlow::Node queryNode; - MongoEngineCall() { this = API::moduleImport("mongoengine") .getMember("Document") .getASubclass() .getMember("objects") - .getACall() and - queryNode = this.getArg(0) + .getACall() } - override DataFlow::Node getQueryNode() { result = queryNode } + override DataFlow::Node getQueryNode() { result = this.getArg(0) } } // pending: look for more Sanitizer libs - private class MongoSanitizer extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { - DataFlow::Node escapeNode; - - MongoSanitizer() { + private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { + MongoSanitizerCall() { this = - API::moduleImport("mongosanitizer").getMember("sanitizer").getMember("sanitize").getACall() and - escapeNode = this.getArg(0) + API::moduleImport("mongosanitizer").getMember("sanitizer").getMember("sanitize").getACall() } - override DataFlow::Node getSanitizerNode() { result = escapeNode } + override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } } } From 5a1dc48e481f5a6da1c7b40e0709a0caafa0e641 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 17:50:31 +0200 Subject: [PATCH 016/429] Fix Mongoengine test --- .../query-tests/Security/CWE-943/flask_mongoengine_bad.py | 2 +- .../query-tests/Security/CWE-943/flask_mongoengine_good.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py index 1f7d4e0ec06..3d7771ca243 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -23,7 +23,7 @@ Movie(title='bb').save() def home_page(): unsanitized_search = json.loads(request.args['search']) - data = Movie.objects(title=unsanitized_search) + data = Movie.objects(unsanitized_search) return data.to_json() # if __name__ == "__main__": diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index 3f515b2ecb8..633feae5a52 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -25,7 +25,7 @@ def home_page(): unsanitized_search = json.loads(request.args['search']) sanitize(unsanitized_search) - data = Movie.objects(title=unsanitized_search) + data = Movie.objects(unsanitized_search) return data.to_json() # if __name__ == "__main__": From 017a826b30954e266173d972ae584ce0cf5351ab Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 17:52:03 +0200 Subject: [PATCH 017/429] Remove unused class variables --- .../semmle/python/security/injection/NoSQLInjection.qll | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 350b1e9273f..7128edc062e 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -9,24 +9,18 @@ import semmle.python.ApiGraphs // custom no-Concepts classes class JsonLoadsCall extends DataFlow::CallCfgNode { - DataFlow::Node loadNode; - JsonLoadsCall() { this = API::moduleImport("json").getMember("loads").getACall() } DataFlow::Node getLoadNode() { result = this.getArg(0) } } class XmlToDictParseCall extends DataFlow::CallCfgNode { - DataFlow::Node parseNode; - XmlToDictParseCall() { this = API::moduleImport("xmltodict").getMember("parse").getACall() } DataFlow::Node getParseNode() { result = this.getArg(0) } } class UltraJsonLoadsCall extends DataFlow::CallCfgNode { - DataFlow::Node loadNode; - UltraJsonLoadsCall() { this = API::moduleImport("ujson").getMember("loads").getACall() } DataFlow::Node getLoadNode() { result = this.getArg(0) } From f0a50eb67a9672cf656e6ce9b40c026a524a6e69 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 17:58:18 +0200 Subject: [PATCH 018/429] Polish up configs --- .../security/injection/NoSQLInjection.qll | 75 +++++-------------- 1 file changed, 17 insertions(+), 58 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 7128edc062e..668c78d7d74 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -26,79 +26,38 @@ class UltraJsonLoadsCall extends DataFlow::CallCfgNode { DataFlow::Node getLoadNode() { result = this.getArg(0) } } -// configs -class XmlToDictParseConfig extends TaintTracking::Configuration { - XmlToDictParseConfig() { this = "XmlToDictParseConfig" } +// better name? +class JSONRelatedSink extends DataFlow::Node { + JSONRelatedSink() { + this = any(JsonLoadsCall jsonLoads).getLoadNode() or + this = any(XmlToDictParseCall jsonLoads).getParseNode() or + this = any(UltraJsonLoadsCall jsonLoads).getLoadNode() + } +} + +class NoSQLInjectionConfig extends TaintTracking::Configuration { + NoSQLInjectionConfig() { this = "NoSQLInjectionConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { - sink = any(XmlToDictParseCall xmlToDictParse).getParseNode() - } + override predicate isSink(DataFlow::Node sink) { sink instanceof JSONRelatedSink } override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() } } -// Must be passed through json.loads(here) since otherwise it would be a string instead of a dict. -class JsonLoadsConfig extends TaintTracking::Configuration { - JsonLoadsConfig() { this = "JsonLoadsConfig" } +// I hate the name ObjectBuilderFunctionConfig so this can be renamed +class ObjectBuilderFunctionConfig extends TaintTracking2::Configuration { + ObjectBuilderFunctionConfig() { this = "ObjectBuilderFunctionConfig" } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + override predicate isSource(DataFlow::Node source) { source instanceof JSONRelatedSink } override predicate isSink(DataFlow::Node sink) { - sink = any(JsonLoadsCall jsonLoads).getLoadNode() + sink = any(NoSQLQuery noSQLQuery).getQueryNode() } override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() } } - -// Must be passed through json.loads(here) since otherwise it would be a string instead of a dict. -class UltraJsonLoadsConfig extends TaintTracking::Configuration { - UltraJsonLoadsConfig() { this = "UltraJsonLoadsConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { - sink = any(UltraJsonLoadsCall ultraCall).getLoadNode() - } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() - } -} - -// This predicate should handle args passed to json, xmltodict, ujson, etc. -class ObjectBuilderMethodArg extends DataFlow::Node { - ObjectBuilderMethodArg() { - this in [ - any(JsonLoadsCall jsonLoads).getLoadNode(), - any(XmlToDictParseCall xmlToDictParse).getParseNode(), - any(UltraJsonLoadsCall ultraCall).getLoadNode() - ] - } -} - -// I don't think this is possible, we should do something like this in the main query: -/** - * config1.hasFlowPath(source, sink) or config2.hasFlowPath(source, sink) or config3.hasFlowPath(source, sink) - * where configs are variables declared from the configs in the list below. - * - * class ObjectBuilderMethod extends DataFlow::Node { - * ObjectBuilderMethod() { this in [JsonLoadsConfig, XmlToDictParseConfig, UltraJsonLoadsConfig] } - *} - */ -class NoSQLInjection extends TaintTracking::Configuration { - NoSQLInjection() { this = "NoSQLInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof ObjectBuilderMethodArg } // Will be JsonLoadsArg - - override predicate isSink(DataFlow::Node sink) { sink instanceof MongoSinks } - - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() - } -} From 3a47a45e47c698be906bb77856d1a09dfd54847c Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 31 Mar 2021 18:49:41 +0200 Subject: [PATCH 019/429] Attempt to apply TaintTracking2 --- .../Security/CWE-943/NoSQLInjection.ql | 7 ++++-- .../semmle/python/frameworks/Stdlib.qll | 2 +- .../security/injection/NoSQLInjection.qll | 24 ++++++++++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index 4fa46ce3ff7..aae531c8ba6 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -12,5 +12,8 @@ import python import experimental.semmle.python.security.injection.NoSQLInjection -import DataFlow::PathGraph -// from, where, select statements + +// https://github.com/github/codeql/blob/e266cedc84cf73d01c9b2d4b0e4313e5d96755ba/python/ql/src/semmle/python/security/dataflow/PathInjection.qll#L103 +from CustomPathNode source, CustomPathNode sink +where noSQLInjectionFlow(source, sink) +select source, sink diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index fb2015939c9..03a5ed30c22 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -62,7 +62,7 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = this.getArg(0) } } - // pending: look for more Sanitizer libs + // more sanitizer libs? private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { MongoSanitizerCall() { this = diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 668c78d7d74..b3e961d7f62 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -1,13 +1,14 @@ import python -import experimental.semmle.python.Concepts import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.DataFlow2 import semmle.python.dataflow.new.TaintTracking -// https://ghsecuritylab.slack.com/archives/CQJU6RN49/p1617022135088100 import semmle.python.dataflow.new.TaintTracking2 +import experimental.semmle.python.Concepts import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.ApiGraphs +// temporary imports (change after query normalization) +import semmle.python.security.dataflow.ChainedConfigs12 -// custom no-Concepts classes class JsonLoadsCall extends DataFlow::CallCfgNode { JsonLoadsCall() { this = API::moduleImport("json").getMember("loads").getACall() } @@ -47,9 +48,9 @@ class NoSQLInjectionConfig extends TaintTracking::Configuration { } } -// I hate the name ObjectBuilderFunctionConfig so this can be renamed -class ObjectBuilderFunctionConfig extends TaintTracking2::Configuration { - ObjectBuilderFunctionConfig() { this = "ObjectBuilderFunctionConfig" } +// better name? +class FromJSONConfig extends TaintTracking2::Configuration { + FromJSONConfig() { this = "FromJSONConfig" } override predicate isSource(DataFlow::Node source) { source instanceof JSONRelatedSink } @@ -61,3 +62,14 @@ class ObjectBuilderFunctionConfig extends TaintTracking2::Configuration { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() } } + +predicate noSQLInjectionFlow(CustomPathNode source, CustomPathNode sink) { + exists( + FromJSONConfig config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, + NoSQLInjectionConfig config2 + | + config.hasFlowPath(source.asNode1(), mid1) and + config2.hasFlowPath(mid2, sink.asNode2()) and + mid1.getNode().asCfgNode() = mid2.getNode().asCfgNode() + ) +} From c8740a2031d5aa5ee5f58d65c3133e2ed6bd4c42 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 1 Apr 2021 12:41:11 +0200 Subject: [PATCH 020/429] Update naming --- .../src/experimental/semmle/python/frameworks/Stdlib.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 03a5ed30c22..aa63ddd105d 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -16,14 +16,14 @@ private module NoSQL { PyMongoMethods() { this in ["find_one"] } } - private class PyMongoCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - PyMongoCall() { + private class PyMongoClientCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + PyMongoClientCall() { this = API::moduleImport("pymongo") .getMember("MongoClient") .getReturn() .getAMember*() - .getMember(any(PyMongoMethods pyMongoM)) + .getMember(any(PyMongoMethods pyMongoMethods)) .getACall() } @@ -42,7 +42,7 @@ private module NoSQL { .getMember("PyMongo") .getReturn() .getAMember*() - .getMember(any(PyMongoFlaskMethods pyMongoFlaskM)) + .getMember(any(PyMongoFlaskMethods pyMongoFlaskMethods)) .getACall() } From f980d0694be7c8d3dd1ee1a6c58e416daa909cec Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 1 Apr 2021 12:50:25 +0200 Subject: [PATCH 021/429] Fix taint configs --- .../experimental/Security/CWE-943/NoSQLInjection.ql | 1 - .../python/security/injection/NoSQLInjection.qll | 11 +++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index aae531c8ba6..23197bb3ce6 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -13,7 +13,6 @@ import python import experimental.semmle.python.security.injection.NoSQLInjection -// https://github.com/github/codeql/blob/e266cedc84cf73d01c9b2d4b0e4313e5d96755ba/python/ql/src/semmle/python/security/dataflow/PathInjection.qll#L103 from CustomPathNode source, CustomPathNode sink where noSQLInjectionFlow(source, sink) select source, sink diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index b3e961d7f62..5e59590448b 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -36,8 +36,8 @@ class JSONRelatedSink extends DataFlow::Node { } } -class NoSQLInjectionConfig extends TaintTracking::Configuration { - NoSQLInjectionConfig() { this = "NoSQLInjectionConfig" } +class RFStoJSON extends TaintTracking::Configuration { + RFStoJSON() { this = "RFStoJSON" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -49,8 +49,8 @@ class NoSQLInjectionConfig extends TaintTracking::Configuration { } // better name? -class FromJSONConfig extends TaintTracking2::Configuration { - FromJSONConfig() { this = "FromJSONConfig" } +class FromJSONtoSink extends TaintTracking2::Configuration { + FromJSONtoSink() { this = "FromJSONtoSink" } override predicate isSource(DataFlow::Node source) { source instanceof JSONRelatedSink } @@ -65,8 +65,7 @@ class FromJSONConfig extends TaintTracking2::Configuration { predicate noSQLInjectionFlow(CustomPathNode source, CustomPathNode sink) { exists( - FromJSONConfig config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, - NoSQLInjectionConfig config2 + RFStoJSON config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, FromJSONtoSink config2 | config.hasFlowPath(source.asNode1(), mid1) and config2.hasFlowPath(mid2, sink.asNode2()) and From 15e176a3b859690e91e605149ef1d190a539d8a7 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 1 Apr 2021 13:00:12 +0200 Subject: [PATCH 022/429] Polish query select --- python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index 23197bb3ce6..c3310379e81 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -15,4 +15,5 @@ import experimental.semmle.python.security.injection.NoSQLInjection from CustomPathNode source, CustomPathNode sink where noSQLInjectionFlow(source, sink) -select source, sink +select sink, source, sink, "$@ NoSQL query contains an unsanitized $@", sink, "This", source, + "user-provided value" From 9072d19cda809124dd57731067221392fc0c6201 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 Apr 2021 13:56:43 -0400 Subject: [PATCH 023/429] Update qhelp file --- .../Security/CWE-943/NoSQLInjection-Bad.py | 15 +++++++++++++ .../Security/CWE-943/NoSQLInjection-Good.py | 9 ++++++++ .../Security/CWE-943/NoSQLInjection.qhelp | 21 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py create mode 100644 python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py new file mode 100644 index 00000000000..0b7abf0740e --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py @@ -0,0 +1,15 @@ +from flask import Flask, request +from flask_pymongo import PyMongo +import json + +app = Flask(__name__) +app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" +mongo = PyMongo(app) + + +@app.route("/") +def home_page(): + unsanitized_search = json.loads(request.args['search']) + + db_results = mongo.db.user.find({'name': unsanitized_search}) + return db_results[0].keys() diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py new file mode 100644 index 00000000000..7bdb64820d3 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py @@ -0,0 +1,9 @@ +# Annotated version +from mongosanitizer.sanitizer import sanitize + +unsanitized_search = json.loads(request.args['search']) + +sanitize(unsanitized_search) + +db_results = mongo.db.user.find({'name': unsanitized_search}) +return db_results[0].keys() diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index 0ca50700f2c..04b7e9c137b 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -4,14 +4,35 @@ +

+ Passing user-controlled sources into NoSQL queries can result in a NoSQL injection flaw. + This tainted NoSQL query will then execute behavior on a NoSQL database like MongoDB that is non-intended by the developer. + It is important to note that in order for the user-controlled source to act or be part of a NoSQL query requires the user-controller source to be converted into a Python object using something like json.loads or xmltodict.parse. +

+ +

+ Because a user-controlled source is directly injected into the query, the malicious user can have complete control over the query itself. + When the query is executed they can commit different types of actions like bypass role restrictions or access and modify restricted data in the MongoDB database. +

+

+ NoSQL injection can be prevented by escaping the user input of special characters that is passed into the NoSQL query. + Alternatively using a sanitize library such as MongoSanitizer to sanitize user input will ensure that users who attempt to construct malicious queries in the user-supplied source is not executed. +

+

In the example below, the user-supplied source is passed to a MongoDB function that queries the MongoDB database.

+ +

This can be fixed by using a sanitizer library like MongoSanitizer as shown in this annotated code version below.

+ +
  • OWASP NoSQL injection : />>
  • +
  • Security Stack Exchange Discussion : />>
  • +
    From be9a3a95b1ed111c5e0943cef47d5b0f12307467 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 Apr 2021 14:23:56 -0400 Subject: [PATCH 024/429] Add relevant PyMongo sink methods --- .../semmle/python/frameworks/Stdlib.qll | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index aa63ddd105d..2097caeca69 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -11,9 +11,14 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSQL { - // more methods? private class PyMongoMethods extends string { - PyMongoMethods() { this in ["find_one"] } + // These are all find-keyword relevant PyMongo collection level operation methods + PyMongoMethods() { + this in [ + "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", + "find_one_and_replace", "find_one_and_update" + ] + } } private class PyMongoClientCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -30,9 +35,8 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = this.getArg(0) } } - // more methods? private class PyMongoFlaskMethods extends string { - PyMongoFlaskMethods() { this in ["find"] } + PyMongoFlaskMethods() { this in ["find_one_or_404"] } } private class PyMongoFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -62,7 +66,6 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = this.getArg(0) } } - // more sanitizer libs? private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { MongoSanitizerCall() { this = From 80216f697441d575adcf5f1512532db8041a70ac Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 Apr 2021 14:41:08 -0400 Subject: [PATCH 025/429] Rename classes --- .../security/injection/NoSQLInjection.qll | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 5e59590448b..bc66a7a472a 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -27,32 +27,30 @@ class UltraJsonLoadsCall extends DataFlow::CallCfgNode { DataFlow::Node getLoadNode() { result = this.getArg(0) } } -// better name? -class JSONRelatedSink extends DataFlow::Node { - JSONRelatedSink() { +class DataToDictSink extends DataFlow::Node { + DataToDictSink() { this = any(JsonLoadsCall jsonLoads).getLoadNode() or this = any(XmlToDictParseCall jsonLoads).getParseNode() or this = any(UltraJsonLoadsCall jsonLoads).getLoadNode() } } -class RFStoJSON extends TaintTracking::Configuration { - RFStoJSON() { this = "RFStoJSON" } +class RFSToDictConfig extends TaintTracking::Configuration { + RFSToDictConfig() { this = "RFSToDictConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { sink instanceof JSONRelatedSink } + override predicate isSink(DataFlow::Node sink) { sink instanceof DataToDictSink } override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() } } -// better name? -class FromJSONtoSink extends TaintTracking2::Configuration { - FromJSONtoSink() { this = "FromJSONtoSink" } +class FromDataDictToSink extends TaintTracking2::Configuration { + FromDataDictToSink() { this = "FromDataDictToSink" } - override predicate isSource(DataFlow::Node source) { source instanceof JSONRelatedSink } + override predicate isSource(DataFlow::Node source) { source instanceof DataToDictSink } override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQueryNode() @@ -65,7 +63,8 @@ class FromJSONtoSink extends TaintTracking2::Configuration { predicate noSQLInjectionFlow(CustomPathNode source, CustomPathNode sink) { exists( - RFStoJSON config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, FromJSONtoSink config2 + RFSToDictConfig config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, + FromDataDictToSink config2 | config.hasFlowPath(source.asNode1(), mid1) and config2.hasFlowPath(mid2, sink.asNode2()) and From 3f0c758622803c7df82b83535a03284aa3d1085f Mon Sep 17 00:00:00 2001 From: thank_you Date: Mon, 5 Apr 2021 19:07:13 -0400 Subject: [PATCH 026/429] Add required __raw__ keyword This __raw__ keyword is required for the actual mongoengine vulnerability. More info can be found below: http://docs.mongoengine.org/guide/querying.html?highlight=inc__#raw-queries --- .../query-tests/Security/CWE-943/flask_mongoengine_bad.py | 2 +- .../query-tests/Security/CWE-943/flask_mongoengine_good.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py index 3d7771ca243..5e084d721ed 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -23,7 +23,7 @@ Movie(title='bb').save() def home_page(): unsanitized_search = json.loads(request.args['search']) - data = Movie.objects(unsanitized_search) + data = Movie.objects(__raw__=unsanitized_search) return data.to_json() # if __name__ == "__main__": diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index 633feae5a52..c90400f0677 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -25,7 +25,7 @@ def home_page(): unsanitized_search = json.loads(request.args['search']) sanitize(unsanitized_search) - data = Movie.objects(unsanitized_search) + data = Movie.objects(__raw__=unsanitized_search) return data.to_json() # if __name__ == "__main__": From 759fa2cd014aab97889d2ef17a42382856d777e1 Mon Sep 17 00:00:00 2001 From: thank_you Date: Mon, 5 Apr 2021 20:42:18 -0400 Subject: [PATCH 027/429] Update query to search for more pymongo sink methods --- python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 2097caeca69..8469a80ae6b 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -36,7 +36,7 @@ private module NoSQL { } private class PyMongoFlaskMethods extends string { - PyMongoFlaskMethods() { this in ["find_one_or_404"] } + PyMongoFlaskMethods() { this in ["find_one_or_404"] or this instanceof PyMongoMethods } } private class PyMongoFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { From 6ade1209834ee2bfc5d6bd69db17d87b8215a832 Mon Sep 17 00:00:00 2001 From: thank_you Date: Mon, 5 Apr 2021 20:44:16 -0400 Subject: [PATCH 028/429] Add check for mongoengine raw queries After initial research on our end, we believe that the only vulnerability within the objects() method is passing a query into the __raw__ keyword argument. More info can be found below: http://docs.mongoengine.org/guide/querying.html?highlight=inc__#raw-queries --- python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 8469a80ae6b..a28e4e15066 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -63,7 +63,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArg(0) } + override DataFlow::Node getQueryNode() { result = this.getArgByName("__raw__") } } private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { From ac31260fed107935e2a0fbb1675ca8361be9803f Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 6 Apr 2021 13:42:57 -0400 Subject: [PATCH 029/429] Made grammar changes --- .../Security/CWE-943/NoSQLInjection.qhelp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index 04b7e9c137b..3dce83dec41 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -12,14 +12,14 @@

    Because a user-controlled source is directly injected into the query, the malicious user can have complete control over the query itself. - When the query is executed they can commit different types of actions like bypass role restrictions or access and modify restricted data in the MongoDB database. + When the query is executed they can commit different types of actions like bypassing role restrictions or accessing and modifying restricted data in the MongoDB database.

    - NoSQL injection can be prevented by escaping the user input of special characters that is passed into the NoSQL query. - Alternatively using a sanitize library such as MongoSanitizer to sanitize user input will ensure that users who attempt to construct malicious queries in the user-supplied source is not executed. + NoSQL injections can be prevented by escaping user-input's special characters that are passed into the NoSQL query from the user-supplied source. + Alternatively using a sanitize library such as MongoSanitizer will ensure that user-supplied sources can not act as a malicious query.

    @@ -31,8 +31,7 @@ -
  • OWASP NoSQL injection : />>
  • -
  • Security Stack Exchange Discussion : />>
  • - +
  • OWASP: NoSQL Injection
  • +
  • Security Stack Exchange Discussion: Question 83231
  • From 520e65e3c3837a8e010386dec6649e6de870c956 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 6 Apr 2021 13:46:51 -0400 Subject: [PATCH 030/429] Remove unnecessary example code --- .../ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py index 7bdb64820d3..96f1db06fce 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py @@ -6,4 +6,3 @@ unsanitized_search = json.loads(request.args['search']) sanitize(unsanitized_search) db_results = mongo.db.user.find({'name': unsanitized_search}) -return db_results[0].keys() From dc274ecf36a3a9f4261d9a8df1ef36e63974e5a0 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 6 Apr 2021 13:51:59 -0400 Subject: [PATCH 031/429] Improve sentence structure and grammar --- .../experimental/Security/CWE-943/NoSQLInjection.qhelp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index 3dce83dec41..b11587901af 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -6,20 +6,20 @@

    Passing user-controlled sources into NoSQL queries can result in a NoSQL injection flaw. - This tainted NoSQL query will then execute behavior on a NoSQL database like MongoDB that is non-intended by the developer. - It is important to note that in order for the user-controlled source to act or be part of a NoSQL query requires the user-controller source to be converted into a Python object using something like json.loads or xmltodict.parse. + This tainted NoSQL query containing a user-controlled source can then execute a malicious query in a NoSQL database such as MongoDB. + In order for the user-controlled source to taint the NoSQL query, the user-controller source must be converted into a Python object using something like json.loads or xmltodict.parse.

    - Because a user-controlled source is directly injected into the query, the malicious user can have complete control over the query itself. - When the query is executed they can commit different types of actions like bypassing role restrictions or accessing and modifying restricted data in the MongoDB database. + Because a user-controlled source is passed into the query, the malicious user can have complete control over the query itself. + When the tainted query is executed, the malicious user can commit malicious actions such as bypassing role restrictions or accessing and modifying restricted data in the NoSQL database.

    NoSQL injections can be prevented by escaping user-input's special characters that are passed into the NoSQL query from the user-supplied source. - Alternatively using a sanitize library such as MongoSanitizer will ensure that user-supplied sources can not act as a malicious query. + Alternatively, using a sanitize library such as MongoSanitizer will ensure that user-supplied sources can not act as a malicious query.

    From 4e98348411a3c6b97b38aae287c2985518fb67d5 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 6 Apr 2021 13:57:03 -0400 Subject: [PATCH 032/429] Remove comment --- .../semmle/python/security/injection/NoSQLInjection.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index bc66a7a472a..2f785de4a21 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -6,7 +6,6 @@ import semmle.python.dataflow.new.TaintTracking2 import experimental.semmle.python.Concepts import semmle.python.dataflow.new.RemoteFlowSources import semmle.python.ApiGraphs -// temporary imports (change after query normalization) import semmle.python.security.dataflow.ChainedConfigs12 class JsonLoadsCall extends DataFlow::CallCfgNode { From 719c30bd92d00129451fec314595bdbcc988afab Mon Sep 17 00:00:00 2001 From: thank_you Date: Wed, 7 Apr 2021 16:42:51 -0400 Subject: [PATCH 033/429] Fix file name and adjust where the test points to --- .../query-tests/Security/CWE-943/NoSQLInjectio.qlref | 1 - .../query-tests/Security/CWE-943/NoSQLInjection.qlref | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref deleted file mode 100644 index dfdfdb51de0..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjectio.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE-943/RegexInjection.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref new file mode 100644 index 00000000000..3ca00df892b --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-943/NoSQLInjection.ql From 83f28bfdda4c06bd92be184f3a10ed31d148cfe9 Mon Sep 17 00:00:00 2001 From: thank_you Date: Wed, 7 Apr 2021 16:45:48 -0400 Subject: [PATCH 034/429] Catch any keyword argument passed to MongoEngine's objects method After some research, we discovered that any keyword argument passed to the objects method will result in NoSQL injection. This includes scenarios where we have the following: objects(name_of_model_attribute=unsanitized_user_input) --- python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index a28e4e15066..267bed6b544 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -63,7 +63,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArgByName("__raw__") } + override DataFlow::Node getQueryNode() { result = this.getArgByName(any(string name)) } } private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { From 0e51dbec8615f1c2dc2767dea68370b69c8d0141 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:29:56 +0200 Subject: [PATCH 035/429] Polish tests --- .../Security/CWE-943/flask_mongoengine_bad.py | 20 ++++++------- .../CWE-943/flask_mongoengine_good.py | 22 +++++++------- .../Security/CWE-943/flask_pymongo_bad.py | 7 ++--- .../Security/CWE-943/flask_pymongo_good.py | 9 +++--- .../Security/CWE-943/mongoengine_bad.py | 28 +++++++++++++++++ .../Security/CWE-943/mongoengine_good.py | 30 +++++++++++++++++++ .../Security/CWE-943/pymongo_bad.py | 6 ++-- .../Security/CWE-943/pymongo_good.py | 8 ++--- 8 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py index 5e084d721ed..b7dca69f70b 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -1,18 +1,18 @@ from flask import Flask, request from flask_mongoengine import MongoEngine -import mongoengine as me import json app = Flask(__name__) db = MongoEngine(app) +db.init_app(app) -class Movie(me.Document): - title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() Movie(title='aa').save() @@ -21,10 +21,10 @@ Movie(title='bb').save() @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) + unsanitized_search = request.args['search'] + json_search = json.loads(unsanitized_search) - data = Movie.objects(__raw__=unsanitized_search) - return data.to_json() + result = Movie.objects(__raw__=json_search) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index c90400f0677..89f6d49a3d1 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -1,19 +1,19 @@ from flask import Flask, request from flask_mongoengine import MongoEngine -import mongoengine as me from mongosanitizer.sanitizer import sanitize import json app = Flask(__name__) db = MongoEngine(app) +db.init_app(app) -class Movie(me.Document): - title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() Movie(title='aa').save() @@ -22,11 +22,11 @@ Movie(title='bb').save() @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) - sanitize(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) - data = Movie.objects(__raw__=unsanitized_search) - return data.to_json() + result = Movie.objects(__raw__=safe_search) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py index 2fec9f0b184..421e2d65a9e 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py @@ -3,16 +3,15 @@ from flask_pymongo import PyMongo import json app = Flask(__name__) -app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" mongo = PyMongo(app) @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) + unsanitized_search = request.args['search'] + json_search = json.loads(unsanitized_search) - db_results = mongo.db.user.find({'name': unsanitized_search}) - return db_results[0].keys() + result = mongo.db.user.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py index 3a0d5545ad0..72907b6ba43 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py @@ -4,17 +4,16 @@ from mongosanitizer.sanitizer import sanitize import json app = Flask(__name__) -app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" mongo = PyMongo(app) @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) - sanitize(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) - db_results = mongo.db.user.find({'name': unsanitized_search}) - return db_results[0].keys() + result = mongo.db.user.find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py new file mode 100644 index 00000000000..c48f7bb9ddb --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py @@ -0,0 +1,28 @@ +from flask import Flask, request +import mongoengine as me +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + data = Movie.objects(__raw__=json_search) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py new file mode 100644 index 00000000000..ac7937195e8 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -0,0 +1,30 @@ +from flask import Flask, request +import mongoengine as me +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + data = Movie.objects(__raw__=safe_search) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py index 46594af9766..e280f90a9f9 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py @@ -8,10 +8,10 @@ client = MongoClient() @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) - db_results = client.db.collection.find_one({'data': unsanitized_search}) - return db_results[0].keys() + result = client.db.collection.find_one({'data': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py index 58b1cd27c7e..f6a113203f9 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py @@ -9,11 +9,11 @@ client = MongoClient() @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) - sanitize(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) - db_results = client.db.collection.find_one({'data': unsanitized_search}) - return db_results[0].keys() + result = client.db.collection.find_one({'data': safe_search}) # if __name__ == "__main__": # app.run(debug=True) From a6b3aefb0bbbab4a3da1d30c078f8ef1a3cd456e Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:30:17 +0200 Subject: [PATCH 036/429] Add flask_mongoengine sink --- .../experimental/semmle/python/frameworks/Stdlib.qll | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 267bed6b544..6ffbf80b5a5 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -53,10 +53,14 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = this.getArg(0) } } - private class MongoEngineCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - MongoEngineCall() { + private class MongoEngineMethods extends string { + MongoEngineMethods() { this in ["mongoengine", "flask_mongoengine"] } + } + + private class MongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + MongoEngineObjectsCall() { this = - API::moduleImport("mongoengine") + API::moduleImport(any(MongoEngineMethods mongoEngineMethod)) .getMember("Document") .getASubclass() .getMember("objects") From fa5869afe7021fc11895e694d6685fdf5600ecb4 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:31:45 +0200 Subject: [PATCH 037/429] Polish qhelp and examples --- .../experimental/Security/CWE-943/NoSQLInjection.qhelp | 9 ++++----- .../NoSQLInjection-bad.py} | 0 .../NoSQLInjection-good.py} | 0 3 files changed, 4 insertions(+), 5 deletions(-) rename python/ql/src/experimental/Security/CWE-943/{NoSQLInjection-Bad.py => examples/NoSQLInjection-bad.py} (100%) rename python/ql/src/experimental/Security/CWE-943/{NoSQLInjection-Good.py => examples/NoSQLInjection-good.py} (100%) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index b11587901af..339fc5d9d14 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -9,7 +9,6 @@ This tainted NoSQL query containing a user-controlled source can then execute a malicious query in a NoSQL database such as MongoDB. In order for the user-controlled source to taint the NoSQL query, the user-controller source must be converted into a Python object using something like json.loads or xmltodict.parse.

    -

    Because a user-controlled source is passed into the query, the malicious user can have complete control over the query itself. When the tainted query is executed, the malicious user can commit malicious actions such as bypassing role restrictions or accessing and modifying restricted data in the NoSQL database. @@ -25,13 +24,13 @@

    In the example below, the user-supplied source is passed to a MongoDB function that queries the MongoDB database.

    - +

    This can be fixed by using a sanitizer library like MongoSanitizer as shown in this annotated code version below.

    - + -
  • OWASP: NoSQL Injection
  • -
  • Security Stack Exchange Discussion: Question 83231
  • +
  • OWASP: NoSQL Injection.
  • +
  • Security Stack Exchange Discussion: Question 83231.
  • diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Bad.py rename to python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py similarity index 100% rename from python/ql/src/experimental/Security/CWE-943/NoSQLInjection-Good.py rename to python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py From 983af32ab525b909ee6f9bf668c007f71af8c7ed Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:36:11 +0200 Subject: [PATCH 038/429] Polish qhelp examples --- .../CWE-943/examples/NoSQLInjection-bad.py | 10 ++++------ .../CWE-943/examples/NoSQLInjection-good.py | 15 +++++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py index 0b7abf0740e..f0071201969 100644 --- a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py +++ b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-bad.py @@ -2,14 +2,12 @@ from flask import Flask, request from flask_pymongo import PyMongo import json -app = Flask(__name__) -app.config["MONGO_URI"] = "mongodb://localhost:27017/testdb" mongo = PyMongo(app) @app.route("/") def home_page(): - unsanitized_search = json.loads(request.args['search']) - - db_results = mongo.db.user.find({'name': unsanitized_search}) - return db_results[0].keys() + unsanitized_search = request.args['search'] + json_search = json.loads(unsanitized_search) + + result = mongo.db.user.find({'name': json_search}) diff --git a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py index 96f1db06fce..8aed7386f8e 100644 --- a/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py +++ b/python/ql/src/experimental/Security/CWE-943/examples/NoSQLInjection-good.py @@ -1,8 +1,15 @@ -# Annotated version +from flask import Flask, request +from flask_pymongo import PyMongo from mongosanitizer.sanitizer import sanitize +import json -unsanitized_search = json.loads(request.args['search']) +mongo = PyMongo(app) -sanitize(unsanitized_search) -db_results = mongo.db.user.find({'name': unsanitized_search}) +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(unsanitized_search) + + result = client.db.collection.find_one({'data': safe_search}) From 208b53e4d2d9d98b16ce955b2c6074489dd1c766 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:36:21 +0200 Subject: [PATCH 039/429] Polish query file --- python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index c3310379e81..cd3909494f3 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -4,7 +4,7 @@ * malicious NoSQL code by the user. * @kind path-problem * @problem.severity error - * @id python/nosql-injection + * @id py/nosql-injection * @tags experimental * security * external/cwe/cwe-943 From 166385755afacd7a069db68bcbcd62421ce44a47 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 21:49:41 +0200 Subject: [PATCH 040/429] Polish Calls naming --- .../ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 6ffbf80b5a5..11f1a5758d5 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -28,7 +28,7 @@ private module NoSQL { .getMember("MongoClient") .getReturn() .getAMember*() - .getMember(any(PyMongoMethods pyMongoMethods)) + .getMember(any(PyMongoMethods pyMongoMethod)) .getACall() } @@ -36,7 +36,7 @@ private module NoSQL { } private class PyMongoFlaskMethods extends string { - PyMongoFlaskMethods() { this in ["find_one_or_404"] or this instanceof PyMongoMethods } + PyMongoFlaskMethods() { this in ["find_one_or_404", any(PyMongoMethods pyMongoMethod)] } } private class PyMongoFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -46,7 +46,7 @@ private module NoSQL { .getMember("PyMongo") .getReturn() .getAMember*() - .getMember(any(PyMongoFlaskMethods pyMongoFlaskMethods)) + .getMember(any(PyMongoFlaskMethods pyMongoFlaskMethod)) .getACall() } From 4615927eeb2efc2c537278575fe254ba7ad73153 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 22:27:53 +0200 Subject: [PATCH 041/429] Fix flask_mongoengine Call --- .../semmle/python/frameworks/Stdlib.qll | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 11f1a5758d5..dc13a50b8dc 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -53,14 +53,25 @@ private module NoSQL { override DataFlow::Node getQueryNode() { result = this.getArg(0) } } - private class MongoEngineMethods extends string { - MongoEngineMethods() { this in ["mongoengine", "flask_mongoengine"] } - } - private class MongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { MongoEngineObjectsCall() { this = - API::moduleImport(any(MongoEngineMethods mongoEngineMethod)) + API::moduleImport("mongoengine") + .getMember("Document") + .getASubclass() + .getMember("objects") + .getACall() + } + + override DataFlow::Node getQueryNode() { result = this.getArgByName(any(string name)) } + } + + private class MongoEngineObjectsFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + MongoEngineObjectsFlaskCall() { + this = + API::moduleImport("flask_mongoengine") + .getMember("MongoEngine") + .getReturn() .getMember("Document") .getASubclass() .getMember("objects") From 5d25a27d62e07d00e00bed0e5e3f3701d9642c78 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 9 Apr 2021 22:28:03 +0200 Subject: [PATCH 042/429] Add .expected --- .../Security/CWE-943/NoSQLInjection.expected | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index e69de29bb2d..9135d887e31 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -0,0 +1,71 @@ +edges +| flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | +| flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | +| flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:26:30:26:42 | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | +| flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | +| flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | +| flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | +| flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | +| flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | +| flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | +| mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | +| pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | +| pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | +| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | +| pymongo_good.py:12:21:12:27 | ControlFlowNode for request | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | +| pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | +| pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | +nodes +| flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:26:30:26:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +#select +| flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | +| flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | +| pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From a4fd70aa3d4b7dbccbbba601695dabc624012414 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 14 Apr 2021 23:35:38 +0300 Subject: [PATCH 043/429] Use don't care expression --- .../src/Security Features/CWE-502/UnsafeDeserialization.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 17438230099..252d2b25ddc 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -19,10 +19,9 @@ where ( sink instanceof InstanceMethodSink and not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, - DataFlow::PathNode safeTypeUsage + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeTypeUsage | - safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and + safeConstructorTracking.hasFlowPath(_, safeTypeUsage) and safeTypeUsage.getNode().asExpr().getParent() = deserializeCall ) or From 3a9d1f46fdb48a70aadec1da01ea2979646e6fa4 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 00:09:19 +0300 Subject: [PATCH 044/429] Hide implementation details --- .../dataflow/UnsafeDeserialization.qll | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index f1486f14f77..ec16a6fc9c6 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -119,7 +119,7 @@ module UnsafeDeserialization { } /** BinaryFormatter */ - predicate isBinaryFormatterCall(MethodCall mc, Method m) { + private predicate isBinaryFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof BinaryFormatterDeserializeMethod and @@ -133,9 +133,9 @@ module UnsafeDeserialization { ) } - abstract class BinaryFormatterSink extends InstanceMethodSink { } + private abstract class BinaryFormatterSink extends InstanceMethodSink { } - class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { + private class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { BinaryFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isBinaryFormatterCall(mc, m) and @@ -145,15 +145,15 @@ module UnsafeDeserialization { } /** SoapFormatter */ - predicate isSoapFormatterCall(MethodCall mc, Method m) { + private predicate isSoapFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof SoapFormatterDeserializeMethod and not mc.getArgument(0).hasValue() } - abstract class SoapFormatterSink extends InstanceMethodSink { } + private abstract class SoapFormatterSink extends InstanceMethodSink { } - class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { + private class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { SoapFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isSoapFormatterCall(mc, m) and @@ -163,15 +163,15 @@ module UnsafeDeserialization { } /** ObjectStateFormatter */ - predicate isObjectStateFormatterCall(MethodCall mc, Method m) { + private predicate isObjectStateFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof ObjectStateFormatterDeserializeMethod and not mc.getArgument(0).hasValue() } - abstract class ObjectStateFormatterSink extends InstanceMethodSink { } + private abstract class ObjectStateFormatterSink extends InstanceMethodSink { } - class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { + private class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { ObjectStateFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isObjectStateFormatterCall(mc, m) and @@ -181,7 +181,7 @@ module UnsafeDeserialization { } /** NetDataContractSerializer */ - predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { + private predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof NetDataContractSerializerDeserializeMethod and @@ -192,9 +192,9 @@ module UnsafeDeserialization { ) } - abstract class NetDataContractSerializerSink extends InstanceMethodSink { } + private abstract class NetDataContractSerializerSink extends InstanceMethodSink { } - class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { + private class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { NetDataContractSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isNetDataContractSerializerCall(mc, m) and @@ -204,15 +204,15 @@ module UnsafeDeserialization { } /** DataContractJsonSerializer */ - predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { + private predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof DataContractJsonSerializerReadObjectMethod and not mc.getArgument(0).hasValue() } - abstract class DataContractJsonSerializerSink extends InstanceMethodSink { } + private abstract class DataContractJsonSerializerSink extends InstanceMethodSink { } - class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { + private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { DataContractJsonSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isDataContractJsonSerializerCall(mc, m) and @@ -221,7 +221,7 @@ module UnsafeDeserialization { } } - class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { DataContractJsonSafeConstructorTrackingConfiguration() { this = "DataContractJsonSafeConstructorTrackingConfiguration" } @@ -242,7 +242,7 @@ module UnsafeDeserialization { } /** JavaScriptSerializer */ - predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { + private predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof JavaScriptSerializerClassDeserializeMethod and @@ -253,9 +253,9 @@ module UnsafeDeserialization { ) } - abstract class JavaScriptSerializerSink extends InstanceMethodSink { } + private abstract class JavaScriptSerializerSink extends InstanceMethodSink { } - class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { + private class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { JavaScriptSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isJavaScriptSerializerCall(mc, m) and @@ -264,7 +264,7 @@ module UnsafeDeserialization { } } - class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { JavaScriptSerializerSafeConstructorTrackingConfiguration() { this = "JavaScriptSerializerSafeConstructorTrackingConfiguration" } @@ -284,16 +284,16 @@ module UnsafeDeserialization { } /** XmlObjectSerializer */ - predicate isXmlObjectSerializerCall(MethodCall mc, Method m) { + private predicate isXmlObjectSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof XmlObjectSerializerReadObjectMethod and not mc.getArgument(0).hasValue() and not mc.targetIsLocalInstance() } - abstract class XmlObjectSerializerSink extends InstanceMethodSink { } + private abstract class XmlObjectSerializerSink extends InstanceMethodSink { } - class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { + private class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { XmlObjectSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isXmlObjectSerializerCall(mc, m) and @@ -302,7 +302,7 @@ module UnsafeDeserialization { } } - class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { XmlObjectSerializerDerivedConstructorTrackingConfiguration() { this = "XmlObjectSerializerDerivedConstructorTrackingConfiguration" } @@ -327,15 +327,15 @@ module UnsafeDeserialization { } /** XmlSerializer */ - predicate isXmlSerializerCall(MethodCall mc, Method m) { + private predicate isXmlSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof XmlSerializerDeserializeMethod and not mc.getArgument(0).hasValue() } - abstract class XmlSerializerSink extends InstanceMethodSink { } + private abstract class XmlSerializerSink extends InstanceMethodSink { } - class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { + private class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { XmlSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isXmlSerializerCall(mc, m) and @@ -344,7 +344,7 @@ module UnsafeDeserialization { } } - class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { XmlSerializerSafeConstructorTrackingConfiguration() { this = "XmlSerializerSafeConstructorTrackingConfiguration" } @@ -364,7 +364,7 @@ module UnsafeDeserialization { } /** DataContractSerializer */ - predicate isDataContractSerializerCall(MethodCall mc, Method m) { + private predicate isDataContractSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof DataContractSerializerReadObjectMethod @@ -374,9 +374,9 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class DataContractSerializerSink extends InstanceMethodSink { } + private abstract class DataContractSerializerSink extends InstanceMethodSink { } - class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { + private class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { DataContractSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | isDataContractSerializerCall(mc, m) and @@ -385,7 +385,7 @@ module UnsafeDeserialization { } } - class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { DataContractSerializerSafeConstructorTrackingConfiguration() { this = "DataContractSerializerSafeConstructorTrackingConfiguration" } @@ -406,15 +406,15 @@ module UnsafeDeserialization { } /** XmlMessageFormatter */ - predicate isXmlMessageFormatterCall(MethodCall mc, Method m) { + private predicate isXmlMessageFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof XmlMessageFormatterReadMethod and not mc.getArgument(0).hasValue() } - abstract class XmlMessageFormatterSink extends InstanceMethodSink { } + private abstract class XmlMessageFormatterSink extends InstanceMethodSink { } - class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { + private class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { XmlMessageFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isXmlMessageFormatterCall(mc, m) and @@ -423,7 +423,7 @@ module UnsafeDeserialization { } } - class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + private class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { XmlMessageFormatterSafeConstructorTrackingConfiguration() { this = "XmlMessageFormatterSafeConstructorTrackingConfiguration" } @@ -444,15 +444,15 @@ module UnsafeDeserialization { } /** LosFormatter */ - predicate isLosFormatterCall(MethodCall mc, Method m) { + private predicate isLosFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof LosFormatterDeserializeMethod and not mc.getArgument(0).hasValue() } - abstract class LosFormatterSink extends InstanceMethodSink { } + private abstract class LosFormatterSink extends InstanceMethodSink { } - class LosFormatterDeserializeMethodSink extends LosFormatterSink { + private class LosFormatterDeserializeMethodSink extends LosFormatterSink { LosFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isLosFormatterCall(mc, m) and @@ -462,15 +462,15 @@ module UnsafeDeserialization { } /** fastJSON */ - predicate isFastJsonCall(MethodCall mc, Method m) { + private predicate isFastJsonCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof FastJsonClassToObjectMethod and not mc.getArgument(0).hasValue() } - abstract class FastJsonSink extends ConstructorOrStaticMethodSink { } + private abstract class FastJsonSink extends ConstructorOrStaticMethodSink { } - class FastJsonDeserializeMethodSink extends FastJsonSink { + private class FastJsonDeserializeMethodSink extends FastJsonSink { FastJsonDeserializeMethodSink() { exists(MethodCall mc, Method m | isFastJsonCall(mc, m) and @@ -480,15 +480,15 @@ module UnsafeDeserialization { } /** Activity */ - predicate isActivityCall(MethodCall mc, Method m) { + private predicate isActivityCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof ActivityLoadMethod and not mc.getArgument(0).hasValue() } - abstract class ActivitySink extends InstanceMethodSink { } + private abstract class ActivitySink extends InstanceMethodSink { } - class ActivityDeserializeMethodSink extends ActivitySink { + private class ActivityDeserializeMethodSink extends ActivitySink { ActivityDeserializeMethodSink() { exists(MethodCall mc, Method m | isActivityCall(mc, m) and @@ -498,15 +498,15 @@ module UnsafeDeserialization { } /** ResourceReader */ - predicate isResourceReaderCall(Call mc, Constructor m) { + private predicate isResourceReaderCall(Call mc, Constructor m) { m = mc.getTarget() and m instanceof ResourceReaderConstructor and not mc.getArgument(0).hasValue() } - abstract class ResourceReaderSink extends ConstructorOrStaticMethodSink { } + private abstract class ResourceReaderSink extends ConstructorOrStaticMethodSink { } - class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { + private class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { ResourceReaderDeserializeMethodSink() { exists(Call mc, Constructor m | isResourceReaderCall(mc, m) and @@ -516,15 +516,15 @@ module UnsafeDeserialization { } /** BinaryMessageFormatter */ - predicate isBinaryMessageFormatterCall(MethodCall mc, Method m) { + private predicate isBinaryMessageFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof BinaryMessageFormatterReadMethod and not mc.getArgument(0).hasValue() } - abstract class BinaryMessageFormatterSink extends InstanceMethodSink { } + private abstract class BinaryMessageFormatterSink extends InstanceMethodSink { } - class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { + private class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { BinaryMessageFormatterDeserializeMethodSink() { exists(MethodCall mc, Method m | isBinaryMessageFormatterCall(mc, m) and @@ -534,7 +534,7 @@ module UnsafeDeserialization { } /** XamlReader */ - predicate isXamlReaderCall(MethodCall mc, Method m) { + private predicate isXamlReaderCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof XamlReaderParseMethod @@ -546,9 +546,9 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class XamlReaderSink extends ConstructorOrStaticMethodSink { } + private abstract class XamlReaderSink extends ConstructorOrStaticMethodSink { } - class XamlReaderDeserializeMethodSink extends XamlReaderSink { + private class XamlReaderDeserializeMethodSink extends XamlReaderSink { XamlReaderDeserializeMethodSink() { exists(MethodCall mc, Method m | isXamlReaderCall(mc, m) and @@ -558,7 +558,7 @@ module UnsafeDeserialization { } /** ProxyObject */ - predicate isProxyObjectCall(MethodCall mc, Method m) { + private predicate isProxyObjectCall(MethodCall mc, Method m) { m = mc.getTarget() and ( m instanceof ProxyObjectDecodeValueMethod @@ -568,9 +568,9 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - abstract class ProxyObjectSink extends InstanceMethodSink { } + private abstract class ProxyObjectSink extends InstanceMethodSink { } - class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { + private class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { ProxyObjectDeserializeMethodSink() { exists(MethodCall mc, Method m | isProxyObjectCall(mc, m) and @@ -580,15 +580,15 @@ module UnsafeDeserialization { } /** SweetJayson */ - predicate isSweetJaysonCall(MethodCall mc, Method m) { + private predicate isSweetJaysonCall(MethodCall mc, Method m) { m = mc.getTarget() and m instanceof JaysonConverterToObjectMethod and not mc.getArgument(0).hasValue() } - abstract class SweetJaysonSink extends ConstructorOrStaticMethodSink { } + private abstract class SweetJaysonSink extends ConstructorOrStaticMethodSink { } - class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { + private class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { SweetJaysonDeserializeMethodSink() { exists(MethodCall mc, Method m | isSweetJaysonCall(mc, m) and @@ -598,9 +598,9 @@ module UnsafeDeserialization { } /** ServiceStack.Text.JsonSerializer */ - abstract class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } + private abstract class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } - class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { + private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { ServiceStackTextJsonSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -619,9 +619,9 @@ module UnsafeDeserialization { } /** ServiceStack.Text.TypeSerializer */ - abstract class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } + private abstract class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } - class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { + private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { ServiceStackTextTypeSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -640,9 +640,9 @@ module UnsafeDeserialization { } /** ServiceStack.Text.CsvSerializer */ - abstract class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } + private abstract class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } - class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { + private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { ServiceStackTextCsvSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -661,9 +661,9 @@ module UnsafeDeserialization { } /** ServiceStack.Text.XmlSerializer */ - abstract class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } + private abstract class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } - class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { + private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { ServiceStackTextXmlSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and From b027fddc7ed5eb1da36cc57d105239972174eff5 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 00:14:09 +0300 Subject: [PATCH 045/429] Remove redundant check --- .../ql/src/Security Features/CWE-502/UnsafeDeserialization.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 252d2b25ddc..7575bd14665 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -25,8 +25,7 @@ where safeTypeUsage.getNode().asExpr().getParent() = deserializeCall ) or - sink instanceof ConstructorOrStaticMethodSink and - deserializeCall.getAnArgument() = sink.asExpr() + sink instanceof ConstructorOrStaticMethodSink ) select deserializeCall, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." From 1581a27d3d4218c7f3239000019a5a2e4a9b74f6 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 15:23:03 +0300 Subject: [PATCH 046/429] Simplify getTarget check --- .../csharp/security/dataflow/UnsafeDeserialization.qll | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index ec16a6fc9c6..5d6b2652fca 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -63,9 +63,8 @@ module UnsafeDeserialization { override predicate isSource(DataFlow::Node source) { source instanceof Source } override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - m instanceof UnsafeDeserializerCallable and + exists(MethodCall mc | + mc.getTarget() instanceof UnsafeDeserializerCallable and sink.asExpr() = mc.getQualifier() ) } @@ -102,9 +101,8 @@ module UnsafeDeserialization { } override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - m instanceof UnsafeDeserializerCallable and + exists(MethodCall mc | + mc.getTarget() instanceof UnsafeDeserializerCallable and sink.asExpr() = mc.getQualifier() ) } From 773556e5e035a7daa2baaa446f2a045fbd04915b Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 15:16:38 +0300 Subject: [PATCH 047/429] Use hasFlow where path is not needed --- .../CWE-502/UnsafeDeserialization.ql | 6 ++--- .../UnsafeDeserializationUntrustedInput.ql | 24 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 7575bd14665..3f5862795e3 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -19,10 +19,10 @@ where ( sink instanceof InstanceMethodSink and not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeTypeUsage + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage | - safeConstructorTracking.hasFlowPath(_, safeTypeUsage) and - safeTypeUsage.getNode().asExpr().getParent() = deserializeCall + safeConstructorTracking.hasFlow(_, safeTypeUsage) and + safeTypeUsage.asExpr().getParent() = deserializeCall ) or sink instanceof ConstructorOrStaticMethodSink diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index de75bf08807..ce85c424f7e 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -33,30 +33,28 @@ where // intersect with strong types, but user controlled or weak types deserialization usages ( exists( - DataFlow::PathNode weakTypeCreation, DataFlow::PathNode weakTypeUsage, + DataFlow::Node weakTypeCreation, DataFlow::Node weakTypeUsage, WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking | - weakTypeDeserializerTracking.hasFlowPath(weakTypeCreation, weakTypeUsage) and - weakTypeUsage.getNode().asExpr().getParent() = - deserializeCallArg.getNode().asExpr().getParent() + weakTypeDeserializerTracking.hasFlow(weakTypeCreation, weakTypeUsage) and + weakTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() ) or exists( - TaintToObjectTypeTrackingConfig userControlledTypeTracking, - DataFlow::PathNode taintedTypeUsage, DataFlow::PathNode userInput2 + TaintToObjectTypeTrackingConfig userControlledTypeTracking, DataFlow::Node taintedTypeUsage, + DataFlow::Node userInput2 | - userControlledTypeTracking.hasFlowPath(userInput2, taintedTypeUsage) and - taintedTypeUsage.getNode().asExpr().getParent() = - deserializeCallArg.getNode().asExpr().getParent() + userControlledTypeTracking.hasFlow(userInput2, taintedTypeUsage) and + taintedTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() ) ) and // exclude deserialization flows with safe instances (i.e. JavaScriptSerializer without resolver) not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::PathNode safeCreation, - DataFlow::PathNode safeTypeUsage + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeCreation, + DataFlow::Node safeTypeUsage | - safeConstructorTracking.hasFlowPath(safeCreation, safeTypeUsage) and - safeTypeUsage.getNode().asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() + safeConstructorTracking.hasFlow(safeCreation, safeTypeUsage) and + safeTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() ) or // no type check needed - straightforward taint -> sink From 3aedd2c1f42c03be87db891031cbc1e7689c54c2 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 22:12:01 +0300 Subject: [PATCH 048/429] Use TaintTracking2 --- .../UnsafeDeserializationUntrustedInput.ql | 10 +-- .../dataflow/UnsafeDeserialization.qll | 7 +- ...safeDeserializationUntrustedInput.expected | 64 ------------------- 3 files changed, 9 insertions(+), 72 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index ce85c424f7e..4e57e256faf 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -24,12 +24,12 @@ class LocalSource extends Source { LocalSource() { this instanceof LocalFlowSource } } -from - TaintToObjectMethodTrackingConfig taintTracking, DataFlow::PathNode userInput, - DataFlow::PathNode deserializeCallArg +from DataFlow::PathNode userInput, DataFlow::PathNode deserializeCallArg where - // all flows from user input to deserialization with weak and strong type serializers - taintTracking.hasFlowPath(userInput, deserializeCallArg) and + exists(TaintToObjectMethodTrackingConfig taintTracking | + // all flows from user input to deserialization with weak and strong type serializers + taintTracking.hasFlowPath(userInput, deserializeCallArg) + ) and // intersect with strong types, but user controlled or weak types deserialization usages ( exists( diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 5d6b2652fca..ec7b4e52b49 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -7,6 +7,7 @@ import csharp module UnsafeDeserialization { private import semmle.code.csharp.serialization.Deserializers + private import semmle.code.csharp.dataflow.TaintTracking2 /** * A data flow source for unsafe deserialization vulnerabilities. @@ -57,7 +58,7 @@ module UnsafeDeserialization { /** * User input to instance type flow tracking. */ - class TaintToObjectTypeTrackingConfig extends TaintTracking::Configuration { + class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration { TaintToObjectTypeTrackingConfig() { this = "TaintToObjectTypeTrackingConfig" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -90,7 +91,7 @@ module UnsafeDeserialization { /** * Unsafe deserializer creation to usage tracking config. */ - class WeakTypeCreationToUsageTrackingConfig extends TaintTracking::Configuration { + class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuration { WeakTypeCreationToUsageTrackingConfig() { this = "DeserializerCreationToUsageTrackingConfig" } override predicate isSource(DataFlow::Node source) { @@ -111,7 +112,7 @@ module UnsafeDeserialization { /** * Safe deserializer creation to usage tracking config. */ - abstract class SafeConstructorTrackingConfig extends TaintTracking::Configuration { + abstract class SafeConstructorTrackingConfig extends TaintTracking2::Configuration { bindingset[this] SafeConstructorTrackingConfig() { any() } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected index 57d849a34b0..5ad68adabc8 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected @@ -1,142 +1,78 @@ edges -| BinaryFormatterUntrustedInputBad.cs:10:18:10:38 | object creation of type BinaryFormatter : BinaryFormatter | BinaryFormatterUntrustedInputBad.cs:12:16:12:17 | access to local variable ds | | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | | BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | -| BinaryFormatterUntrustedInputGood.cs:9:18:9:38 | object creation of type BinaryFormatter : BinaryFormatter | BinaryFormatterUntrustedInputGood.cs:11:16:11:17 | access to local variable ds | -| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:65 | access to parameter type : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | -| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractJsonSerializerUntrustedInputGood.cs:12:18:12:87 | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | DataContractJsonSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | | DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:65 | access to parameter type : TextBox | DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | DataContractJsonSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | -| DataContractSerializerUntrustedInputBad.cs:11:58:11:61 | access to parameter type : TextBox | DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | -| DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | DataContractSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractSerializerUntrustedInputGood.cs:12:18:12:79 | object creation of type DataContractSerializer : DataContractSerializer | DataContractSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | | DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | | DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractSerializerUntrustedInputGood.cs:18:58:18:61 | access to parameter type : TextBox | DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | DataContractSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | -| UnsafeDeserializationUntrustedInputBad.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | UnsafeDeserializationUntrustedInputBad.cs:10:16:10:17 | access to local variable sr | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | -| UnsafeDeserializationUntrustedInputGood.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | UnsafeDeserializationUntrustedInputGood.cs:10:16:10:17 | access to local variable sr | -| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:77 | access to parameter type : TextBox | XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | -| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | XmlObjectSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| XmlObjectSerializerUntrustedInputGood.cs:12:34:12:92 | object creation of type DataContractSerializer : DataContractSerializer | XmlObjectSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | | XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:77 | access to parameter type : TextBox | XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | XmlObjectSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | -| XmlSerializerUntrustedInputBad.cs:11:49:11:52 | access to parameter type : TextBox | XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | -| XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | -| XmlSerializerUntrustedInputGood.cs:12:18:12:61 | object creation of type XmlSerializer : XmlSerializer | XmlSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | | XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | | XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | | XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | -| XmlSerializerUntrustedInputGood.cs:18:49:18:52 | access to parameter type : TextBox | XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | XmlSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | nodes -| BinaryFormatterUntrustedInputBad.cs:10:18:10:38 | object creation of type BinaryFormatter : BinaryFormatter | semmle.label | object creation of type BinaryFormatter : BinaryFormatter | -| BinaryFormatterUntrustedInputBad.cs:12:16:12:17 | access to local variable ds | semmle.label | access to local variable ds | | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox | | BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | semmle.label | access to property Text : String | -| BinaryFormatterUntrustedInputGood.cs:9:18:9:38 | object creation of type BinaryFormatter : BinaryFormatter | semmle.label | object creation of type BinaryFormatter : BinaryFormatter | -| BinaryFormatterUntrustedInputGood.cs:11:16:11:17 | access to local variable ds | semmle.label | access to local variable ds | -| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:65 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| DataContractJsonSerializerUntrustedInputBad.cs:11:62:11:70 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractJsonSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:12:18:12:87 | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | semmle.label | object creation of type DataContractJsonSerializer : DataContractJsonSerializer | -| DataContractJsonSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:65 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| DataContractJsonSerializerUntrustedInputGood.cs:18:62:18:70 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | -| DataContractSerializerUntrustedInputBad.cs:11:58:11:61 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| DataContractSerializerUntrustedInputBad.cs:11:58:11:66 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:12:18:12:79 | object creation of type DataContractSerializer : DataContractSerializer | semmle.label | object creation of type DataContractSerializer : DataContractSerializer | -| DataContractSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:18:58:18:61 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| DataContractSerializerUntrustedInputGood.cs:18:58:18:66 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | semmle.label | access to property Text : String | -| UnsafeDeserializationUntrustedInputBad.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | semmle.label | object creation of type JavaScriptSerializer : JavaScriptSerializer | -| UnsafeDeserializationUntrustedInputBad.cs:10:16:10:17 | access to local variable sr | semmle.label | access to local variable sr | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:43 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox | | UnsafeDeserializationUntrustedInputBad.cs:10:37:10:48 | access to property Text | semmle.label | access to property Text | -| UnsafeDeserializationUntrustedInputGood.cs:8:35:8:84 | object creation of type JavaScriptSerializer : JavaScriptSerializer | semmle.label | object creation of type JavaScriptSerializer : JavaScriptSerializer | -| UnsafeDeserializationUntrustedInputGood.cs:10:16:10:17 | access to local variable sr | semmle.label | access to local variable sr | -| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:77 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| XmlObjectSerializerUntrustedInputBad.cs:11:74:11:82 | access to property Text : String | semmle.label | access to property Text : String | -| XmlObjectSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:12:34:12:92 | object creation of type DataContractSerializer : DataContractSerializer | semmle.label | object creation of type DataContractSerializer : DataContractSerializer | -| XmlObjectSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:77 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| XmlObjectSerializerUntrustedInputGood.cs:18:74:18:82 | access to property Text : String | semmle.label | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | -| XmlSerializerUntrustedInputBad.cs:11:49:11:52 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| XmlSerializerUntrustedInputBad.cs:11:49:11:57 | access to property Text : String | semmle.label | access to property Text : String | -| XmlSerializerUntrustedInputBad.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:12:18:12:61 | object creation of type XmlSerializer : XmlSerializer | semmle.label | object creation of type XmlSerializer : XmlSerializer | -| XmlSerializerUntrustedInputGood.cs:13:16:13:17 | access to local variable ds | semmle.label | access to local variable ds | | XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:18:49:18:52 | access to parameter type : TextBox | semmle.label | access to parameter type : TextBox | -| XmlSerializerUntrustedInputGood.cs:18:49:18:57 | access to property Text : String | semmle.label | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:20:16:20:17 | access to local variable ds | semmle.label | access to local variable ds | #select | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | User-provided data | | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data | From a412581556d0e6bfd0f3b14cb3a14fd7751edf06 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 15 Apr 2021 22:32:42 +0300 Subject: [PATCH 049/429] reintroduce UnsafeDeserializer --- .../csharp/serialization/Deserializers.qll | 79 ++++++++++--------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index bf9c74e645b..6f70c205159 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -5,6 +5,9 @@ import csharp +/** An unsafe deserializer. */ +abstract class UnsafeDeserializer extends Callable { } + /** Unsafe deserialization calls. */ class UnsafeDeserializerCallable extends Callable { UnsafeDeserializerCallable() { @@ -140,7 +143,7 @@ class WeakTypeDeserializer extends Class { * An unsafe deserializer method that calls any unsafe deserializer on any of * the parameters. */ -class WrapperDeserializer extends UnsafeDeserializerCallable { +class WrapperDeserializer extends UnsafeDeserializerCallable, UnsafeDeserializer { WrapperDeserializer() { exists(Call call | call.getEnclosingCallable() = this and @@ -157,21 +160,21 @@ class BinaryFormatterClass extends Class { } } -class BinaryFormatterDeserializeMethod extends Method { +class BinaryFormatterDeserializeMethod extends Method, UnsafeDeserializer { BinaryFormatterDeserializeMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and this.hasName("Deserialize") } } -class BinaryFormatterUnsafeDeserializeMethod extends Method { +class BinaryFormatterUnsafeDeserializeMethod extends Method, UnsafeDeserializer { BinaryFormatterUnsafeDeserializeMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and this.hasName("UnsafeDeserialize") } } -class BinaryFormatterUnsafeDeserializeMethodResponseMethod extends Method { +class BinaryFormatterUnsafeDeserializeMethodResponseMethod extends Method, UnsafeDeserializer { BinaryFormatterUnsafeDeserializeMethodResponseMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and this.hasName("UnsafeDeserializeMethodResponse") @@ -185,7 +188,7 @@ class SoapFormatterClass extends Class { } } -class SoapFormatterDeserializeMethod extends Method { +class SoapFormatterDeserializeMethod extends Method, UnsafeDeserializer { SoapFormatterDeserializeMethod() { this.getDeclaringType() instanceof SoapFormatterClass and this.hasName("Deserialize") @@ -197,7 +200,7 @@ class ObjectStateFormatterClass extends Class { ObjectStateFormatterClass() { this.hasQualifiedName("System.Web.UI.ObjectStateFormatter") } } -class ObjectStateFormatterDeserializeMethod extends Method { +class ObjectStateFormatterDeserializeMethod extends Method, UnsafeDeserializer { ObjectStateFormatterDeserializeMethod() { this.getDeclaringType() instanceof ObjectStateFormatterClass and this.hasName("Deserialize") @@ -211,14 +214,14 @@ class NetDataContractSerializerClass extends Class { } } -class NetDataContractSerializerDeserializeMethod extends Method { +class NetDataContractSerializerDeserializeMethod extends Method, UnsafeDeserializer { NetDataContractSerializerDeserializeMethod() { this.getDeclaringType() instanceof NetDataContractSerializerClass and this.hasName("Deserialize") } } -class NetDataContractSerializerReadObjectMethod extends Method { +class NetDataContractSerializerReadObjectMethod extends Method, UnsafeDeserializer { NetDataContractSerializerReadObjectMethod() { this.getDeclaringType() instanceof NetDataContractSerializerClass and this.hasName("ReadObject") @@ -232,7 +235,7 @@ class DataContractJsonSerializerClass extends Class { } } -class DataContractJsonSerializerReadObjectMethod extends Method { +class DataContractJsonSerializerReadObjectMethod extends Method, UnsafeDeserializer { DataContractJsonSerializerReadObjectMethod() { this.getDeclaringType() instanceof DataContractJsonSerializerClass and this.hasName("ReadObject") @@ -246,14 +249,14 @@ class JavaScriptSerializerClass extends Class { } } -class JavaScriptSerializerClassDeserializeMethod extends Method { +class JavaScriptSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { JavaScriptSerializerClassDeserializeMethod() { this.getDeclaringType() instanceof JavaScriptSerializerClass and this.hasName("Deserialize") } } -class JavaScriptSerializerClassDeserializeObjectMethod extends Method { +class JavaScriptSerializerClassDeserializeObjectMethod extends Method, UnsafeDeserializer { JavaScriptSerializerClassDeserializeObjectMethod() { this.getDeclaringType() instanceof JavaScriptSerializerClass and this.hasName("DeserializeObject") @@ -267,7 +270,7 @@ class XmlObjectSerializerClass extends Class { } } -class XmlObjectSerializerReadObjectMethod extends Method { +class XmlObjectSerializerReadObjectMethod extends Method, UnsafeDeserializer { XmlObjectSerializerReadObjectMethod() { this.getDeclaringType() instanceof XmlObjectSerializerClass and this.hasName("ReadObject") @@ -279,7 +282,7 @@ class XmlSerializerClass extends Class { XmlSerializerClass() { this.hasQualifiedName("System.Xml.Serialization.XmlSerializer") } } -class XmlSerializerDeserializeMethod extends Method { +class XmlSerializerDeserializeMethod extends Method, UnsafeDeserializer { XmlSerializerDeserializeMethod() { this.getDeclaringType() instanceof XmlSerializerClass and this.hasName("Deserialize") @@ -293,7 +296,7 @@ class DataContractSerializerClass extends Class { } } -class DataContractSerializerReadObjectMethod extends Method { +class DataContractSerializerReadObjectMethod extends Method, UnsafeDeserializer { DataContractSerializerReadObjectMethod() { this.getDeclaringType() instanceof DataContractSerializerClass and this.hasName("ReadObject") @@ -305,7 +308,7 @@ class XmlMessageFormatterClass extends Class { XmlMessageFormatterClass() { this.hasQualifiedName("System.Messaging.XmlMessageFormatter") } } -class XmlMessageFormatterReadMethod extends Method { +class XmlMessageFormatterReadMethod extends Method, UnsafeDeserializer { XmlMessageFormatterReadMethod() { this.getDeclaringType() instanceof XmlMessageFormatterClass and this.hasName("Read") @@ -317,7 +320,7 @@ class LosFormatterClass extends Class { LosFormatterClass() { this.hasQualifiedName("System.Web.UI.LosFormatter") } } -class LosFormatterDeserializeMethod extends Method { +class LosFormatterDeserializeMethod extends Method, UnsafeDeserializer { LosFormatterDeserializeMethod() { this.getDeclaringType() instanceof LosFormatterClass and this.hasName("Deserialize") @@ -329,7 +332,7 @@ class FastJsonClass extends Class { FastJsonClass() { this.hasQualifiedName("fastJSON.JSON") } } -class FastJsonClassToObjectMethod extends Method { +class FastJsonClassToObjectMethod extends Method, UnsafeDeserializer { FastJsonClassToObjectMethod() { this.getDeclaringType() instanceof FastJsonClass and this.hasName("ToObject") and @@ -342,7 +345,7 @@ class ActivityClass extends Class { ActivityClass() { this.hasQualifiedName("System.Workflow.ComponentModel.Activity") } } -class ActivityLoadMethod extends Method { +class ActivityLoadMethod extends Method, UnsafeDeserializer { ActivityLoadMethod() { this.getDeclaringType() instanceof ActivityClass and this.hasName("Load") @@ -354,7 +357,7 @@ class ResourceReaderClass extends Class { ResourceReaderClass() { this.hasQualifiedName("System.Resources.ResourceReader") } } -class ResourceReaderConstructor extends Constructor { +class ResourceReaderConstructor extends Constructor, UnsafeDeserializer { ResourceReaderConstructor() { this.getDeclaringType() instanceof ResourceReaderClass and this.hasName("ResourceReader") @@ -366,7 +369,7 @@ class BinaryMessageFormatterClass extends Class { BinaryMessageFormatterClass() { this.hasQualifiedName("System.Messaging.BinaryMessageFormatter") } } -class BinaryMessageFormatterReadMethod extends Method { +class BinaryMessageFormatterReadMethod extends Method, UnsafeDeserializer { BinaryMessageFormatterReadMethod() { this.getDeclaringType() instanceof BinaryMessageFormatterClass and this.hasName("Read") @@ -378,7 +381,7 @@ class XamlReaderClass extends Class { XamlReaderClass() { this.hasQualifiedName("System.Windows.Markup.XamlReader") } } -class XamlReaderParseMethod extends Method { +class XamlReaderParseMethod extends Method, UnsafeDeserializer { XamlReaderParseMethod() { this.getDeclaringType() instanceof XamlReaderClass and this.hasName("Parse") and @@ -386,7 +389,7 @@ class XamlReaderParseMethod extends Method { } } -class XamlReaderLoadMethod extends Method { +class XamlReaderLoadMethod extends Method, UnsafeDeserializer { XamlReaderLoadMethod() { this.getDeclaringType() instanceof XamlReaderClass and this.hasName("Load") and @@ -394,7 +397,7 @@ class XamlReaderLoadMethod extends Method { } } -class XamlReaderLoadAsyncMethod extends Method { +class XamlReaderLoadAsyncMethod extends Method, UnsafeDeserializer { XamlReaderLoadAsyncMethod() { this.getDeclaringType() instanceof XamlReaderClass and this.hasName("LoadAsync") @@ -406,14 +409,14 @@ class ProxyObjectClass extends Class { ProxyObjectClass() { this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject") } } -class ProxyObjectDecodeValueMethod extends Method { +class ProxyObjectDecodeValueMethod extends Method, UnsafeDeserializer { ProxyObjectDecodeValueMethod() { this.getDeclaringType() instanceof ProxyObjectClass and this.hasName("DecodeValue") } } -class ProxyObjectDecodeSerializedObjectMethod extends Method { +class ProxyObjectDecodeSerializedObjectMethod extends Method, UnsafeDeserializer { ProxyObjectDecodeSerializedObjectMethod() { this.getDeclaringType() instanceof ProxyObjectClass and this.hasName("DecodeSerializedObject") @@ -425,7 +428,7 @@ class JaysonConverterClass extends Class { JaysonConverterClass() { this.hasQualifiedName("Sweet.Jayson.JaysonConverter") } } -class JaysonConverterToObjectMethod extends Method { +class JaysonConverterToObjectMethod extends Method, UnsafeDeserializer { JaysonConverterToObjectMethod() { this.getDeclaringType() instanceof JaysonConverterClass and this.hasName("ToObject") and @@ -440,7 +443,7 @@ class ServiceStackTextJsonSerializerClass extends Class { } } -class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method { +class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and this.hasName("DeserializeFromString") and @@ -448,7 +451,7 @@ class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method { } } -class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method { +class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and this.hasName("DeserializeFromReader") and @@ -456,7 +459,7 @@ class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method { } } -class ServiceStackTextJsonSerializerDeserializeFromStreamMethod extends Method { +class ServiceStackTextJsonSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and this.hasName("DeserializeFromStream") and @@ -471,7 +474,7 @@ class ServiceStackTextTypeSerializerClass extends Class { } } -class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method { +class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and this.hasName("DeserializeFromString") and @@ -479,7 +482,7 @@ class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method { } } -class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method { +class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and this.hasName("DeserializeFromReader") and @@ -487,7 +490,7 @@ class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method { } } -class ServiceStackTextTypeSerializerDeserializeFromStreamMethod extends Method { +class ServiceStackTextTypeSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and this.hasName("DeserializeFromStream") and @@ -500,7 +503,7 @@ class ServiceStackTextCsvSerializerClass extends Class { ServiceStackTextCsvSerializerClass() { this.hasQualifiedName("ServiceStack.Text.CsvSerializer") } } -class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method { +class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and this.hasName("DeserializeFromString") and @@ -508,7 +511,7 @@ class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method { } } -class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method { +class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and this.hasName("DeserializeFromReader") and @@ -516,7 +519,7 @@ class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method { } } -class ServiceStackTextCsvSerializerDeserializeFromStreamMethod extends Method { +class ServiceStackTextCsvSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and this.hasName("DeserializeFromStream") and @@ -529,7 +532,7 @@ class ServiceStackTextXmlSerializerClass extends Class { ServiceStackTextXmlSerializerClass() { this.hasQualifiedName("ServiceStack.Text.XmlSerializer") } } -class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method { +class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and this.hasName("DeserializeFromString") and @@ -537,7 +540,7 @@ class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method { } } -class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method { +class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and this.hasName("DeserializeFromReader") and @@ -545,7 +548,7 @@ class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method { } } -class ServiceStackTextXmlSerializerDeserializeFromStreamMethod extends Method { +class ServiceStackTextXmlSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and this.hasName("DeserializeFromStream") and From c3deb48efab9e440a051d93542899c0dc89b848c Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Fri, 16 Apr 2021 17:19:42 +0300 Subject: [PATCH 050/429] Charpred for InstanceMethodSink --- .../CWE-502/UnsafeDeserialization.ql | 12 +--- .../dataflow/UnsafeDeserialization.qll | 64 ++++++++++++------- ...safeDeserializationUntrustedInput.expected | 28 -------- 3 files changed, 41 insertions(+), 63 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index 3f5862795e3..e7c3eb2b4e9 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -16,16 +16,6 @@ import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeseria from Call deserializeCall, DataFlow::Node sink where deserializeCall.getAnArgument() = sink.asExpr() and - ( - sink instanceof InstanceMethodSink and - not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage - | - safeConstructorTracking.hasFlow(_, safeTypeUsage) and - safeTypeUsage.asExpr().getParent() = deserializeCall - ) - or - sink instanceof ConstructorOrStaticMethodSink - ) + sink instanceof Sink select deserializeCall, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index ec7b4e52b49..753d2c457e4 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -14,15 +14,29 @@ module UnsafeDeserialization { */ abstract class Source extends DataFlow::Node { } + /** + * A data flow sink for unsafe deserialization vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { } + /** * A data flow sink for unsafe deserialization vulnerabilities to an instance method. */ - abstract class InstanceMethodSink extends DataFlow::Node { } + abstract private class InstanceMethodSink extends Sink { + InstanceMethodSink() { + not exists( + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage + | + safeConstructorTracking.hasFlow(_, safeTypeUsage) and + safeTypeUsage.asExpr().getParent() = this.asExpr().getParent() + ) + } + } /** * A data flow sink for unsafe deserialization vulnerabilities to a static method or constructor call. */ - abstract class ConstructorOrStaticMethodSink extends DataFlow::Node { } + abstract private class ConstructorOrStaticMethodSink extends Sink { } /** * A sanitizer for unsafe deserialization vulnerabilities. @@ -132,7 +146,7 @@ module UnsafeDeserialization { ) } - private abstract class BinaryFormatterSink extends InstanceMethodSink { } + abstract private class BinaryFormatterSink extends InstanceMethodSink { } private class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { BinaryFormatterDeserializeMethodSink() { @@ -150,7 +164,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class SoapFormatterSink extends InstanceMethodSink { } + abstract private class SoapFormatterSink extends InstanceMethodSink { } private class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { SoapFormatterDeserializeMethodSink() { @@ -168,7 +182,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class ObjectStateFormatterSink extends InstanceMethodSink { } + abstract private class ObjectStateFormatterSink extends InstanceMethodSink { } private class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { ObjectStateFormatterDeserializeMethodSink() { @@ -191,7 +205,7 @@ module UnsafeDeserialization { ) } - private abstract class NetDataContractSerializerSink extends InstanceMethodSink { } + abstract private class NetDataContractSerializerSink extends InstanceMethodSink { } private class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { NetDataContractSerializerDeserializeMethodSink() { @@ -209,7 +223,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class DataContractJsonSerializerSink extends InstanceMethodSink { } + abstract private class DataContractJsonSerializerSink extends InstanceMethodSink { } private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { DataContractJsonSerializerDeserializeMethodSink() { @@ -252,7 +266,7 @@ module UnsafeDeserialization { ) } - private abstract class JavaScriptSerializerSink extends InstanceMethodSink { } + abstract private class JavaScriptSerializerSink extends InstanceMethodSink { } private class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { JavaScriptSerializerDeserializeMethodSink() { @@ -290,7 +304,7 @@ module UnsafeDeserialization { not mc.targetIsLocalInstance() } - private abstract class XmlObjectSerializerSink extends InstanceMethodSink { } + abstract private class XmlObjectSerializerSink extends InstanceMethodSink { } private class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { XmlObjectSerializerDeserializeMethodSink() { @@ -332,7 +346,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class XmlSerializerSink extends InstanceMethodSink { } + abstract private class XmlSerializerSink extends InstanceMethodSink { } private class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { XmlSerializerDeserializeMethodSink() { @@ -373,7 +387,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class DataContractSerializerSink extends InstanceMethodSink { } + abstract private class DataContractSerializerSink extends InstanceMethodSink { } private class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { DataContractSerializerDeserializeMethodSink() { @@ -411,7 +425,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class XmlMessageFormatterSink extends InstanceMethodSink { } + abstract private class XmlMessageFormatterSink extends InstanceMethodSink { } private class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { XmlMessageFormatterDeserializeMethodSink() { @@ -449,7 +463,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class LosFormatterSink extends InstanceMethodSink { } + abstract private class LosFormatterSink extends InstanceMethodSink { } private class LosFormatterDeserializeMethodSink extends LosFormatterSink { LosFormatterDeserializeMethodSink() { @@ -467,7 +481,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class FastJsonSink extends ConstructorOrStaticMethodSink { } + abstract private class FastJsonSink extends ConstructorOrStaticMethodSink { } private class FastJsonDeserializeMethodSink extends FastJsonSink { FastJsonDeserializeMethodSink() { @@ -485,7 +499,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class ActivitySink extends InstanceMethodSink { } + abstract private class ActivitySink extends InstanceMethodSink { } private class ActivityDeserializeMethodSink extends ActivitySink { ActivityDeserializeMethodSink() { @@ -503,7 +517,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class ResourceReaderSink extends ConstructorOrStaticMethodSink { } + abstract private class ResourceReaderSink extends ConstructorOrStaticMethodSink { } private class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { ResourceReaderDeserializeMethodSink() { @@ -521,7 +535,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class BinaryMessageFormatterSink extends InstanceMethodSink { } + abstract private class BinaryMessageFormatterSink extends InstanceMethodSink { } private class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { BinaryMessageFormatterDeserializeMethodSink() { @@ -545,7 +559,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class XamlReaderSink extends ConstructorOrStaticMethodSink { } + abstract private class XamlReaderSink extends ConstructorOrStaticMethodSink { } private class XamlReaderDeserializeMethodSink extends XamlReaderSink { XamlReaderDeserializeMethodSink() { @@ -567,7 +581,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class ProxyObjectSink extends InstanceMethodSink { } + abstract private class ProxyObjectSink extends InstanceMethodSink { } private class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { ProxyObjectDeserializeMethodSink() { @@ -585,7 +599,7 @@ module UnsafeDeserialization { not mc.getArgument(0).hasValue() } - private abstract class SweetJaysonSink extends ConstructorOrStaticMethodSink { } + abstract private class SweetJaysonSink extends ConstructorOrStaticMethodSink { } private class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { SweetJaysonDeserializeMethodSink() { @@ -597,7 +611,8 @@ module UnsafeDeserialization { } /** ServiceStack.Text.JsonSerializer */ - private abstract class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } + abstract private class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { + } private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { ServiceStackTextJsonSerializerDeserializeMethodSink() { @@ -618,7 +633,8 @@ module UnsafeDeserialization { } /** ServiceStack.Text.TypeSerializer */ - private abstract class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } + abstract private class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { + } private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { ServiceStackTextTypeSerializerDeserializeMethodSink() { @@ -639,7 +655,7 @@ module UnsafeDeserialization { } /** ServiceStack.Text.CsvSerializer */ - private abstract class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } + abstract private class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { ServiceStackTextCsvSerializerDeserializeMethodSink() { @@ -660,7 +676,7 @@ module UnsafeDeserialization { } /** ServiceStack.Text.XmlSerializer */ - private abstract class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } + abstract private class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { ServiceStackTextXmlSerializerDeserializeMethodSink() { diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected index 5ad68adabc8..7d36370b2e3 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected @@ -5,15 +5,9 @@ edges | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | -| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | -| DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | | ResourceReaderUntrustedInputBad.cs:11:77:11:85 | access to property Text : String | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | @@ -21,15 +15,9 @@ edges | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | -| XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | -| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | -| XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | -| XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | nodes | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | @@ -39,18 +27,10 @@ nodes | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractJsonSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | -| DataContractJsonSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | -| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | -| DataContractJsonSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | DataContractSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | DataContractSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| DataContractSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | -| DataContractSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | -| DataContractSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | -| DataContractSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | ResourceReaderUntrustedInputBad.cs:11:54:11:86 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | @@ -61,18 +41,10 @@ nodes | XmlObjectSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | -| XmlObjectSerializerUntrustedInputGood.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | -| XmlObjectSerializerUntrustedInputGood.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | -| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | -| XmlObjectSerializerUntrustedInputGood.cs:13:70:13:78 | access to property Text : String | semmle.label | access to property Text : String | | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | -| XmlSerializerUntrustedInputGood.cs:13:31:13:81 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream | -| XmlSerializerUntrustedInputGood.cs:13:48:13:80 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] | -| XmlSerializerUntrustedInputGood.cs:13:71:13:74 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox | -| XmlSerializerUntrustedInputGood.cs:13:71:13:79 | access to property Text : String | semmle.label | access to property Text : String | #select | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | User-provided data | | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data | From bbd3552392c5ab978fe8322e703b821389893878 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 20 Apr 2021 08:47:37 -0400 Subject: [PATCH 051/429] Rename predicate to getQuery --- python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++-- .../src/experimental/semmle/python/frameworks/Stdlib.qll | 8 ++++---- .../semmle/python/security/injection/NoSQLInjection.qll | 4 +--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index ff418437f8a..fec3e5c7ea1 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -16,7 +16,7 @@ private import experimental.semmle.python.Frameworks module NoSQLQuery { abstract class Range extends DataFlow::Node { - abstract DataFlow::Node getQueryNode(); + abstract DataFlow::Node getQuery(); } } @@ -25,7 +25,7 @@ class NoSQLQuery extends DataFlow::Node { NoSQLQuery() { this = range } - DataFlow::Node getQueryNode() { result = range.getQueryNode() } + DataFlow::Node getQuery() { result = range.getQuery() } } module NoSQLSanitizer { diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index dc13a50b8dc..4ae1b2b104a 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -32,7 +32,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArg(0) } + override DataFlow::Node getQuery() { result = this.getArg(0) } } private class PyMongoFlaskMethods extends string { @@ -50,7 +50,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArg(0) } + override DataFlow::Node getQuery() { result = this.getArg(0) } } private class MongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -63,7 +63,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArgByName(any(string name)) } + override DataFlow::Node getQuery() { result = this.getArgByName(any(string name)) } } private class MongoEngineObjectsFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -78,7 +78,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQueryNode() { result = this.getArgByName(any(string name)) } + override DataFlow::Node getQuery() { result = this.getArgByName(any(string name)) } } private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 2f785de4a21..27109bb3439 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -51,9 +51,7 @@ class FromDataDictToSink extends TaintTracking2::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof DataToDictSink } - override predicate isSink(DataFlow::Node sink) { - sink = any(NoSQLQuery noSQLQuery).getQueryNode() - } + override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQuery() } override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() From 7773c531248417e7d90c419b05971f1e36ba2792 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 20 Apr 2021 08:49:08 -0400 Subject: [PATCH 052/429] Replace any(string) with _ wildcard --- .../ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 4ae1b2b104a..177d7a1a560 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -63,7 +63,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQuery() { result = this.getArgByName(any(string name)) } + override DataFlow::Node getQuery() { result = this.getArgByName(_) } } private class MongoEngineObjectsFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { @@ -78,7 +78,7 @@ private module NoSQL { .getACall() } - override DataFlow::Node getQuery() { result = this.getArgByName(any(string name)) } + override DataFlow::Node getQuery() { result = this.getArgByName(_) } } private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { From 3ac5f7bb18aa16b4c99a55bfda7cf5c3e304eb1e Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 13:27:26 +0300 Subject: [PATCH 053/429] Move RemoteSource and LocalSource to UnsafeDeserialization.qll --- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 10 ---------- .../csharp/security/dataflow/UnsafeDeserialization.qll | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 4e57e256faf..44302bc2cdf 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -13,16 +13,6 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph -import semmle.code.csharp.security.dataflow.flowsources.Remote -import semmle.code.csharp.security.dataflow.flowsources.Local - -class RemoteSource extends Source { - RemoteSource() { this instanceof RemoteFlowSource } -} - -class LocalSource extends Source { - LocalSource() { this instanceof LocalFlowSource } -} from DataFlow::PathNode userInput, DataFlow::PathNode deserializeCallArg where diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 753d2c457e4..a41bba54f09 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -8,6 +8,8 @@ import csharp module UnsafeDeserialization { private import semmle.code.csharp.serialization.Deserializers private import semmle.code.csharp.dataflow.TaintTracking2 + private import semmle.code.csharp.security.dataflow.flowsources.Remote + private import semmle.code.csharp.security.dataflow.flowsources.Local /** * A data flow source for unsafe deserialization vulnerabilities. @@ -43,6 +45,14 @@ module UnsafeDeserialization { */ abstract class Sanitizer extends DataFlow::Node { } + class RemoteSource extends Source { + RemoteSource() { this instanceof RemoteFlowSource } + } + + class LocalSource extends Source { + LocalSource() { this instanceof LocalFlowSource } + } + /** * User input to object method call deserialization flow tracking. */ From 0590522e4bb3962c214a314e1300f0486373e749 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 13:29:00 +0300 Subject: [PATCH 054/429] a deserializer --- .../ql/src/semmle/code/csharp/serialization/Deserializers.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 6f70c205159..ce50b10ba45 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -87,7 +87,7 @@ class UnsafeDeserializerCallable extends Callable { } } -/** Deserializer exploitable only if user controls the expected object type. */ +/** A deserializer exploitable only if user controls the expected object type. */ class StrongTypeDeserializer extends Class { StrongTypeDeserializer() { this instanceof XmlSerializerClass @@ -100,7 +100,7 @@ class StrongTypeDeserializer extends Class { } } -/** Deserializer that doesn't make strong expected type check. */ +/** A deserializer that doesn't make strong expected type check. */ class WeakTypeDeserializer extends Class { WeakTypeDeserializer() { this instanceof BinaryFormatterClass From 8f6411dba30ba0ae30199a298e5fb2dbbbd06ccf Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 13:52:41 +0300 Subject: [PATCH 055/429] Simpify with exists --- .../dataflow/UnsafeDeserialization.qll | 151 +++++++++++------- 1 file changed, 97 insertions(+), 54 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index a41bba54f09..41eb322eb76 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -48,7 +48,7 @@ module UnsafeDeserialization { class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } - + class LocalSource extends Source { LocalSource() { this instanceof LocalFlowSource } } @@ -145,14 +145,14 @@ module UnsafeDeserialization { private predicate isBinaryFormatterCall(MethodCall mc, Method m) { m = mc.getTarget() and ( - m instanceof BinaryFormatterDeserializeMethod and - not mc.getArgument(0).hasValue() - or - m instanceof BinaryFormatterUnsafeDeserializeMethod and - not mc.getArgument(0).hasValue() - or - m instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod and - not mc.getArgument(0).hasValue() + not mc.getArgument(0).hasValue() and + ( + m instanceof BinaryFormatterDeserializeMethod + or + m instanceof BinaryFormatterUnsafeDeserializeMethod + or + m instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod + ) ) } @@ -207,10 +207,11 @@ module UnsafeDeserialization { private predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and ( - m instanceof NetDataContractSerializerDeserializeMethod and - not mc.getArgument(0).hasValue() - or - m instanceof NetDataContractSerializerReadObjectMethod and + ( + m instanceof NetDataContractSerializerDeserializeMethod + or + m instanceof NetDataContractSerializerReadObjectMethod + ) and not mc.getArgument(0).hasValue() ) } @@ -250,10 +251,15 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - DataContractJsonSerializerClass and - source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and - source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof DataContractJsonSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -268,10 +274,11 @@ module UnsafeDeserialization { private predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { m = mc.getTarget() and ( - m instanceof JavaScriptSerializerClassDeserializeMethod and - not mc.getArgument(0).hasValue() - or - m instanceof JavaScriptSerializerClassDeserializeObjectMethod and + ( + m instanceof JavaScriptSerializerClassDeserializeMethod + or + m instanceof JavaScriptSerializerClassDeserializeObjectMethod + ) and not mc.getArgument(0).hasValue() ) } @@ -293,9 +300,14 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - JavaScriptSerializerClass and - source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() = 0 + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof JavaScriptSerializerClass and + c.getNumberOfParameters() = 0 + ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -331,13 +343,16 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType().getABaseType+() instanceof - XmlObjectSerializerClass and - not ( - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - DataContractSerializerClass or - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - NetDataContractSerializerClass + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(ValueOrRefType declaringType | + declaringType = oc.getTarget().getDeclaringType() and + declaringType.getABaseType+() instanceof XmlObjectSerializerClass and + not ( + declaringType instanceof DataContractSerializerClass or + declaringType instanceof NetDataContractSerializerClass + ) + ) ) } @@ -373,9 +388,15 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof XmlSerializerClass and - source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and - source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof XmlSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -414,10 +435,15 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - DataContractSerializerClass and - source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and - source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof DataContractSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -452,10 +478,15 @@ module UnsafeDeserialization { } override predicate isSource(DataFlow::Node source) { - source.asExpr().(ObjectCreation).getTarget().getDeclaringType() instanceof - XmlMessageFormatterClass and - source.asExpr().(ObjectCreation).getTarget().getNumberOfParameters() > 0 and - source.asExpr().(ObjectCreation).getArgument(0) instanceof TypeofExpr + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof XmlMessageFormatterClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -635,9 +666,12 @@ module UnsafeDeserialization { or m instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod ) and - not mc.getAnArgument().hasValue() and - not mc.getAnArgument() instanceof TypeofExpr and - this.asExpr() = mc.getAnArgument() + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) ) } } @@ -657,9 +691,12 @@ module UnsafeDeserialization { or m instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod ) and - not mc.getAnArgument().hasValue() and - not mc.getAnArgument() instanceof TypeofExpr and - this.asExpr() = mc.getAnArgument() + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) ) } } @@ -678,9 +715,12 @@ module UnsafeDeserialization { or m instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod ) and - not mc.getAnArgument().hasValue() and - not mc.getAnArgument() instanceof TypeofExpr and - this.asExpr() = mc.getAnArgument() + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) ) } } @@ -699,9 +739,12 @@ module UnsafeDeserialization { or m instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod ) and - not mc.getAnArgument().hasValue() and - not mc.getAnArgument() instanceof TypeofExpr and - this.asExpr() = mc.getAnArgument() + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) ) } } From 9cc67e426671c0fd642d747cfec2bce3d95557dc Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:48:05 +0300 Subject: [PATCH 056/429] make private where possible --- .../csharp/serialization/Deserializers.qll | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index ce50b10ba45..de1f793c1ef 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -143,7 +143,7 @@ class WeakTypeDeserializer extends Class { * An unsafe deserializer method that calls any unsafe deserializer on any of * the parameters. */ -class WrapperDeserializer extends UnsafeDeserializerCallable, UnsafeDeserializer { +private class WrapperDeserializer extends UnsafeDeserializerCallable, UnsafeDeserializer { WrapperDeserializer() { exists(Call call | call.getEnclosingCallable() = this and @@ -154,7 +154,7 @@ class WrapperDeserializer extends UnsafeDeserializerCallable, UnsafeDeserializer } /** BinaryFormatter */ -class BinaryFormatterClass extends Class { +private class BinaryFormatterClass extends Class { BinaryFormatterClass() { this.hasQualifiedName("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter") } @@ -182,7 +182,7 @@ class BinaryFormatterUnsafeDeserializeMethodResponseMethod extends Method, Unsaf } /** SoapFormatter */ -class SoapFormatterClass extends Class { +private class SoapFormatterClass extends Class { SoapFormatterClass() { this.hasQualifiedName("System.Runtime.Serialization.Formatters.Soap.SoapFormatter") } @@ -196,7 +196,7 @@ class SoapFormatterDeserializeMethod extends Method, UnsafeDeserializer { } /** ObjectStateFormatter */ -class ObjectStateFormatterClass extends Class { +private class ObjectStateFormatterClass extends Class { ObjectStateFormatterClass() { this.hasQualifiedName("System.Web.UI.ObjectStateFormatter") } } @@ -316,7 +316,7 @@ class XmlMessageFormatterReadMethod extends Method, UnsafeDeserializer { } /** LosFormatter */ -class LosFormatterClass extends Class { +private class LosFormatterClass extends Class { LosFormatterClass() { this.hasQualifiedName("System.Web.UI.LosFormatter") } } @@ -328,7 +328,7 @@ class LosFormatterDeserializeMethod extends Method, UnsafeDeserializer { } /** fastJSON */ -class FastJsonClass extends Class { +private class FastJsonClass extends Class { FastJsonClass() { this.hasQualifiedName("fastJSON.JSON") } } @@ -341,7 +341,7 @@ class FastJsonClassToObjectMethod extends Method, UnsafeDeserializer { } /** Activity */ -class ActivityClass extends Class { +private class ActivityClass extends Class { ActivityClass() { this.hasQualifiedName("System.Workflow.ComponentModel.Activity") } } @@ -353,7 +353,7 @@ class ActivityLoadMethod extends Method, UnsafeDeserializer { } /** ResourceReader */ -class ResourceReaderClass extends Class { +private class ResourceReaderClass extends Class { ResourceReaderClass() { this.hasQualifiedName("System.Resources.ResourceReader") } } @@ -365,7 +365,7 @@ class ResourceReaderConstructor extends Constructor, UnsafeDeserializer { } /** BinaryMessageFormatter */ -class BinaryMessageFormatterClass extends Class { +private class BinaryMessageFormatterClass extends Class { BinaryMessageFormatterClass() { this.hasQualifiedName("System.Messaging.BinaryMessageFormatter") } } @@ -377,7 +377,7 @@ class BinaryMessageFormatterReadMethod extends Method, UnsafeDeserializer { } /** XamlReader */ -class XamlReaderClass extends Class { +private class XamlReaderClass extends Class { XamlReaderClass() { this.hasQualifiedName("System.Windows.Markup.XamlReader") } } @@ -405,7 +405,7 @@ class XamlReaderLoadAsyncMethod extends Method, UnsafeDeserializer { } /** ProxyObject */ -class ProxyObjectClass extends Class { +private class ProxyObjectClass extends Class { ProxyObjectClass() { this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject") } } @@ -424,7 +424,7 @@ class ProxyObjectDecodeSerializedObjectMethod extends Method, UnsafeDeserializer } /** SweetJayson */ -class JaysonConverterClass extends Class { +private class JaysonConverterClass extends Class { JaysonConverterClass() { this.hasQualifiedName("Sweet.Jayson.JaysonConverter") } } @@ -437,7 +437,7 @@ class JaysonConverterToObjectMethod extends Method, UnsafeDeserializer { } /** ServiceStack.Text.JsonSerializer */ -class ServiceStackTextJsonSerializerClass extends Class { +private class ServiceStackTextJsonSerializerClass extends Class { ServiceStackTextJsonSerializerClass() { this.hasQualifiedName("ServiceStack.Text.JsonSerializer") } @@ -468,7 +468,7 @@ class ServiceStackTextJsonSerializerDeserializeFromStreamMethod extends Method, } /** ServiceStack.Text.TypeSerializer */ -class ServiceStackTextTypeSerializerClass extends Class { +private class ServiceStackTextTypeSerializerClass extends Class { ServiceStackTextTypeSerializerClass() { this.hasQualifiedName("ServiceStack.Text.TypeSerializer") } @@ -499,7 +499,7 @@ class ServiceStackTextTypeSerializerDeserializeFromStreamMethod extends Method, } /** ServiceStack.Text.CsvSerializer */ -class ServiceStackTextCsvSerializerClass extends Class { +private class ServiceStackTextCsvSerializerClass extends Class { ServiceStackTextCsvSerializerClass() { this.hasQualifiedName("ServiceStack.Text.CsvSerializer") } } @@ -528,7 +528,7 @@ class ServiceStackTextCsvSerializerDeserializeFromStreamMethod extends Method, U } /** ServiceStack.Text.XmlSerializer */ -class ServiceStackTextXmlSerializerClass extends Class { +private class ServiceStackTextXmlSerializerClass extends Class { ServiceStackTextXmlSerializerClass() { this.hasQualifiedName("ServiceStack.Text.XmlSerializer") } } From b6952d541ae37a655722c24be4822544629f29e1 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:55:34 +0300 Subject: [PATCH 057/429] get rid of getParent --- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 44302bc2cdf..839f9615e26 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -24,18 +24,20 @@ where ( exists( DataFlow::Node weakTypeCreation, DataFlow::Node weakTypeUsage, - WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking + WeakTypeCreationToUsageTrackingConfig weakTypeDeserializerTracking, MethodCall mc | weakTypeDeserializerTracking.hasFlow(weakTypeCreation, weakTypeUsage) and - weakTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() + mc.getQualifier() = weakTypeUsage.asExpr() and + mc.getAnArgument() = deserializeCallArg.getNode().asExpr() ) or exists( TaintToObjectTypeTrackingConfig userControlledTypeTracking, DataFlow::Node taintedTypeUsage, - DataFlow::Node userInput2 + DataFlow::Node userInput2, MethodCall mc | userControlledTypeTracking.hasFlow(userInput2, taintedTypeUsage) and - taintedTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() + mc.getQualifier() = taintedTypeUsage.asExpr() and + mc.getAnArgument() = deserializeCallArg.getNode().asExpr() ) ) and // exclude deserialization flows with safe instances (i.e. JavaScriptSerializer without resolver) From 808444986d44490308df2505fd5e6083de92c040 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:06:20 +0300 Subject: [PATCH 058/429] Get rid of UnsafeDeserializerCallable --- .../CWE-502/DeserializedDelegate.ql | 2 +- .../dataflow/UnsafeDeserialization.qll | 4 +- .../csharp/serialization/Deserializers.qll | 83 +------------------ 3 files changed, 5 insertions(+), 84 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql b/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql index 75708e712dc..31d28311908 100644 --- a/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql +++ b/csharp/ql/src/Security Features/CWE-502/DeserializedDelegate.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.serialization.Deserializers from Call deserialization, Cast cast where - deserialization.getTarget() instanceof UnsafeDeserializerCallable and + deserialization.getTarget() instanceof UnsafeDeserializer and cast.getExpr() = deserialization and cast.getTargetType() instanceof SystemLinqExpressions::DelegateExtType select deserialization, "Deserialization of delegate type." diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 41eb322eb76..6c78f745037 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -89,7 +89,7 @@ module UnsafeDeserialization { override predicate isSink(DataFlow::Node sink) { exists(MethodCall mc | - mc.getTarget() instanceof UnsafeDeserializerCallable and + mc.getTarget() instanceof UnsafeDeserializer and sink.asExpr() = mc.getQualifier() ) } @@ -127,7 +127,7 @@ module UnsafeDeserialization { override predicate isSink(DataFlow::Node sink) { exists(MethodCall mc | - mc.getTarget() instanceof UnsafeDeserializerCallable and + mc.getTarget() instanceof UnsafeDeserializer and sink.asExpr() = mc.getQualifier() ) } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index de1f793c1ef..9dcbeda5acf 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -8,85 +8,6 @@ import csharp /** An unsafe deserializer. */ abstract class UnsafeDeserializer extends Callable { } -/** Unsafe deserialization calls. */ -class UnsafeDeserializerCallable extends Callable { - UnsafeDeserializerCallable() { - this instanceof BinaryFormatterDeserializeMethod - or - this instanceof BinaryFormatterUnsafeDeserializeMethod - or - this instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod - or - this instanceof SoapFormatterDeserializeMethod - or - this instanceof ObjectStateFormatterDeserializeMethod - or - this instanceof NetDataContractSerializerDeserializeMethod - or - this instanceof NetDataContractSerializerReadObjectMethod - or - this instanceof DataContractJsonSerializerReadObjectMethod - or - this instanceof JavaScriptSerializerClassDeserializeMethod - or - this instanceof JavaScriptSerializerClassDeserializeObjectMethod - or - this instanceof XmlObjectSerializerReadObjectMethod - or - this instanceof XmlSerializerDeserializeMethod - or - this instanceof DataContractSerializerReadObjectMethod - or - this instanceof XmlMessageFormatterReadMethod - or - this instanceof LosFormatterDeserializeMethod - or - this instanceof FastJsonClassToObjectMethod - or - this instanceof ActivityLoadMethod - or - this instanceof ResourceReaderConstructor - or - this instanceof BinaryMessageFormatterReadMethod - or - this instanceof XamlReaderParseMethod - or - this instanceof XamlReaderLoadMethod - or - this instanceof XamlReaderLoadAsyncMethod - or - this instanceof ProxyObjectDecodeValueMethod - or - this instanceof ProxyObjectDecodeSerializedObjectMethod - or - this instanceof JaysonConverterToObjectMethod - or - this instanceof ServiceStackTextJsonSerializerDeserializeFromStringMethod - or - this instanceof ServiceStackTextJsonSerializerDeserializeFromReaderMethod - or - this instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod - or - this instanceof ServiceStackTextTypeSerializerDeserializeFromStringMethod - or - this instanceof ServiceStackTextTypeSerializerDeserializeFromReaderMethod - or - this instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod - or - this instanceof ServiceStackTextCsvSerializerDeserializeFromStringMethod - or - this instanceof ServiceStackTextCsvSerializerDeserializeFromReaderMethod - or - this instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod - or - this instanceof ServiceStackTextXmlSerializerDeserializeFromStringMethod - or - this instanceof ServiceStackTextXmlSerializerDeserializeFromReaderMethod - or - this instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod - } -} - /** A deserializer exploitable only if user controls the expected object type. */ class StrongTypeDeserializer extends Class { StrongTypeDeserializer() { @@ -143,12 +64,12 @@ class WeakTypeDeserializer extends Class { * An unsafe deserializer method that calls any unsafe deserializer on any of * the parameters. */ -private class WrapperDeserializer extends UnsafeDeserializerCallable, UnsafeDeserializer { +private class WrapperDeserializer extends UnsafeDeserializer { WrapperDeserializer() { exists(Call call | call.getEnclosingCallable() = this and call.getAnArgument() instanceof ParameterAccess and - call.getTarget() instanceof UnsafeDeserializerCallable + call.getTarget() instanceof UnsafeDeserializer ) } } From 9e46ef3cd9768ff7da2d0a2a4e71455ca46fad55 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:11:40 +0300 Subject: [PATCH 059/429] Get rid of getParent --- .../code/csharp/security/dataflow/UnsafeDeserialization.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 6c78f745037..181a27d6d2d 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -27,10 +27,12 @@ module UnsafeDeserialization { abstract private class InstanceMethodSink extends Sink { InstanceMethodSink() { not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage, + MethodCall mc | safeConstructorTracking.hasFlow(_, safeTypeUsage) and - safeTypeUsage.asExpr().getParent() = this.asExpr().getParent() + mc.getQualifier() = safeTypeUsage.asExpr() and + mc.getAnArgument() = this.asExpr() ) } } From a93d6a3ef66fba1562bfd89d8200db001e0ecc58 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 17:16:54 +0300 Subject: [PATCH 060/429] Remove SafeConstructorTrackingConfig --- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 8 -------- 1 file changed, 8 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 839f9615e26..2aeb41e4ceb 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -39,14 +39,6 @@ where mc.getQualifier() = taintedTypeUsage.asExpr() and mc.getAnArgument() = deserializeCallArg.getNode().asExpr() ) - ) and - // exclude deserialization flows with safe instances (i.e. JavaScriptSerializer without resolver) - not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeCreation, - DataFlow::Node safeTypeUsage - | - safeConstructorTracking.hasFlow(safeCreation, safeTypeUsage) and - safeTypeUsage.asExpr().getParent() = deserializeCallArg.getNode().asExpr().getParent() ) or // no type check needed - straightforward taint -> sink From 57689df5aa880fb5eb5ecf621a62e726ccde5b19 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 21 Apr 2021 19:29:30 +0300 Subject: [PATCH 061/429] Remove DataFlow::Node --- .../src/Security Features/CWE-502/UnsafeDeserialization.ql | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index e7c3eb2b4e9..40022d40573 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -13,9 +13,7 @@ import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization -from Call deserializeCall, DataFlow::Node sink -where - deserializeCall.getAnArgument() = sink.asExpr() and - sink instanceof Sink +from Call deserializeCall, Sink sink +where deserializeCall.getAnArgument() = sink.asExpr() select deserializeCall, "Unsafe deserializer is used. Make sure the value being deserialized comes from a trusted source." From c9c9758e014f7771728d4f732020fa956a16cf8e Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:23:46 +0300 Subject: [PATCH 062/429] Make similarly named files in tests and qhelp in sync --- .../CWE-502/UnsafeDeserializationUntrustedInputGood.cs | 2 +- .../UnsafeDeserializationUntrustedInputGood.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputGood.cs b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputGood.cs index d1e2935b218..d6b5b09841b 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputGood.cs +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInputGood.cs @@ -6,7 +6,7 @@ class Good public static object Deserialize(TextBox textBox) { JavaScriptSerializer sr = new JavaScriptSerializer(); - // GOOD + // GOOD: no unsafe type resolver return sr.DeserializeObject(textBox.Text); } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs index 05222245f9a..d6b5b09841b 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputGood.cs @@ -5,8 +5,8 @@ class Good { public static object Deserialize(TextBox textBox) { - JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver()); - // GOOD - return sr.DeserializeObject("hardcoded"); + JavaScriptSerializer sr = new JavaScriptSerializer(); + // GOOD: no unsafe type resolver + return sr.DeserializeObject(textBox.Text); } } From 62f3e8d64a4f75fc6fdf21dbeafaa66685f91e39 Mon Sep 17 00:00:00 2001 From: thank_you Date: Mon, 26 Apr 2021 15:35:42 -0400 Subject: [PATCH 063/429] Add sanitizer for ObjectId ObjectId is a sanitizer used to sanitize strings into valid MongoDB ids. During research we've found that this method is used. ObjectId returns a string representing an id. If at any time ObjectId can't parse it's input (like when a tainted dict in passed in), then ObjectId will throw an error preventing the query from running. --- .../experimental/semmle/python/frameworks/Stdlib.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 177d7a1a560..09777dd1037 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -89,4 +89,15 @@ private module NoSQL { override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } } + + private class BsonObjectIdCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { + BsonObjectIdCall() { + this = + API::moduleImport(["bson", "bson.objectid", "bson.json_util"]) + .getMember("ObjectId") + .getACall() + } + + override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } + } } From 18a3e4d45b233a301e959cc2e1b390a5eb16ce55 Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Tue, 27 Apr 2021 22:10:04 +0300 Subject: [PATCH 064/429] add comments --- .../dataflow/UnsafeDeserialization.qll | 4 +- .../csharp/serialization/Deserializers.qll | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 181a27d6d2d..407d7b22bbc 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -47,11 +47,11 @@ module UnsafeDeserialization { */ abstract class Sanitizer extends DataFlow::Node { } - class RemoteSource extends Source { + private class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } - class LocalSource extends Source { + private class LocalSource extends Source { LocalSource() { this instanceof LocalFlowSource } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 9dcbeda5acf..58b6375bc13 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -81,6 +81,7 @@ private class BinaryFormatterClass extends Class { } } +/** `System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize` method */ class BinaryFormatterDeserializeMethod extends Method, UnsafeDeserializer { BinaryFormatterDeserializeMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and @@ -88,6 +89,7 @@ class BinaryFormatterDeserializeMethod extends Method, UnsafeDeserializer { } } +/** `System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.UnsafeDeserialize` method */ class BinaryFormatterUnsafeDeserializeMethod extends Method, UnsafeDeserializer { BinaryFormatterUnsafeDeserializeMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and @@ -95,6 +97,7 @@ class BinaryFormatterUnsafeDeserializeMethod extends Method, UnsafeDeserializer } } +/** `System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.UnsafeDeserializeMethodResponse` method */ class BinaryFormatterUnsafeDeserializeMethodResponseMethod extends Method, UnsafeDeserializer { BinaryFormatterUnsafeDeserializeMethodResponseMethod() { this.getDeclaringType() instanceof BinaryFormatterClass and @@ -109,6 +112,7 @@ private class SoapFormatterClass extends Class { } } +/** `System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize` method */ class SoapFormatterDeserializeMethod extends Method, UnsafeDeserializer { SoapFormatterDeserializeMethod() { this.getDeclaringType() instanceof SoapFormatterClass and @@ -121,6 +125,7 @@ private class ObjectStateFormatterClass extends Class { ObjectStateFormatterClass() { this.hasQualifiedName("System.Web.UI.ObjectStateFormatter") } } +/** `System.Web.UI.ObjectStateFormatter.Deserialize` method */ class ObjectStateFormatterDeserializeMethod extends Method, UnsafeDeserializer { ObjectStateFormatterDeserializeMethod() { this.getDeclaringType() instanceof ObjectStateFormatterClass and @@ -135,6 +140,7 @@ class NetDataContractSerializerClass extends Class { } } +/** `System.Runtime.Serialization.NetDataContractSerializer.Deserialize` method */ class NetDataContractSerializerDeserializeMethod extends Method, UnsafeDeserializer { NetDataContractSerializerDeserializeMethod() { this.getDeclaringType() instanceof NetDataContractSerializerClass and @@ -142,6 +148,7 @@ class NetDataContractSerializerDeserializeMethod extends Method, UnsafeDeseriali } } +/** `System.Runtime.Serialization.NetDataContractSerializer.ReadObject` method */ class NetDataContractSerializerReadObjectMethod extends Method, UnsafeDeserializer { NetDataContractSerializerReadObjectMethod() { this.getDeclaringType() instanceof NetDataContractSerializerClass and @@ -156,6 +163,7 @@ class DataContractJsonSerializerClass extends Class { } } +/** `System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject` method */ class DataContractJsonSerializerReadObjectMethod extends Method, UnsafeDeserializer { DataContractJsonSerializerReadObjectMethod() { this.getDeclaringType() instanceof DataContractJsonSerializerClass and @@ -170,6 +178,7 @@ class JavaScriptSerializerClass extends Class { } } +/** `System.Web.Script.Serialization.JavaScriptSerializer.Deserialize` method */ class JavaScriptSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { JavaScriptSerializerClassDeserializeMethod() { this.getDeclaringType() instanceof JavaScriptSerializerClass and @@ -177,6 +186,7 @@ class JavaScriptSerializerClassDeserializeMethod extends Method, UnsafeDeseriali } } +/** `System.Web.Script.Serialization.JavaScriptSerializer.DeserializeObject` method */ class JavaScriptSerializerClassDeserializeObjectMethod extends Method, UnsafeDeserializer { JavaScriptSerializerClassDeserializeObjectMethod() { this.getDeclaringType() instanceof JavaScriptSerializerClass and @@ -191,6 +201,7 @@ class XmlObjectSerializerClass extends Class { } } +/** `System.Runtime.Serialization.XmlObjectSerializer.ReadObject` method */ class XmlObjectSerializerReadObjectMethod extends Method, UnsafeDeserializer { XmlObjectSerializerReadObjectMethod() { this.getDeclaringType() instanceof XmlObjectSerializerClass and @@ -203,6 +214,7 @@ class XmlSerializerClass extends Class { XmlSerializerClass() { this.hasQualifiedName("System.Xml.Serialization.XmlSerializer") } } +/** `System.Xml.Serialization.XmlSerializer.Deserialize` method */ class XmlSerializerDeserializeMethod extends Method, UnsafeDeserializer { XmlSerializerDeserializeMethod() { this.getDeclaringType() instanceof XmlSerializerClass and @@ -217,6 +229,7 @@ class DataContractSerializerClass extends Class { } } +/** `System.Runtime.Serialization.DataContractSerializer.ReadObject` method */ class DataContractSerializerReadObjectMethod extends Method, UnsafeDeserializer { DataContractSerializerReadObjectMethod() { this.getDeclaringType() instanceof DataContractSerializerClass and @@ -229,6 +242,7 @@ class XmlMessageFormatterClass extends Class { XmlMessageFormatterClass() { this.hasQualifiedName("System.Messaging.XmlMessageFormatter") } } +/** `System.Messaging.XmlMessageFormatter.Read` method */ class XmlMessageFormatterReadMethod extends Method, UnsafeDeserializer { XmlMessageFormatterReadMethod() { this.getDeclaringType() instanceof XmlMessageFormatterClass and @@ -241,6 +255,7 @@ private class LosFormatterClass extends Class { LosFormatterClass() { this.hasQualifiedName("System.Web.UI.LosFormatter") } } +/** `System.Web.UI.LosFormatter.Deserialize` method */ class LosFormatterDeserializeMethod extends Method, UnsafeDeserializer { LosFormatterDeserializeMethod() { this.getDeclaringType() instanceof LosFormatterClass and @@ -253,6 +268,7 @@ private class FastJsonClass extends Class { FastJsonClass() { this.hasQualifiedName("fastJSON.JSON") } } +/** `fastJSON.JSON.ToObject` method */ class FastJsonClassToObjectMethod extends Method, UnsafeDeserializer { FastJsonClassToObjectMethod() { this.getDeclaringType() instanceof FastJsonClass and @@ -266,6 +282,7 @@ private class ActivityClass extends Class { ActivityClass() { this.hasQualifiedName("System.Workflow.ComponentModel.Activity") } } +/** `System.Workflow.ComponentModel.Activity.Load` method */ class ActivityLoadMethod extends Method, UnsafeDeserializer { ActivityLoadMethod() { this.getDeclaringType() instanceof ActivityClass and @@ -278,6 +295,7 @@ private class ResourceReaderClass extends Class { ResourceReaderClass() { this.hasQualifiedName("System.Resources.ResourceReader") } } +/** `System.Resources.ResourceReader` constructor */ class ResourceReaderConstructor extends Constructor, UnsafeDeserializer { ResourceReaderConstructor() { this.getDeclaringType() instanceof ResourceReaderClass and @@ -290,6 +308,7 @@ private class BinaryMessageFormatterClass extends Class { BinaryMessageFormatterClass() { this.hasQualifiedName("System.Messaging.BinaryMessageFormatter") } } +/** `System.Messaging.BinaryMessageFormatter.Read` method */ class BinaryMessageFormatterReadMethod extends Method, UnsafeDeserializer { BinaryMessageFormatterReadMethod() { this.getDeclaringType() instanceof BinaryMessageFormatterClass and @@ -302,6 +321,7 @@ private class XamlReaderClass extends Class { XamlReaderClass() { this.hasQualifiedName("System.Windows.Markup.XamlReader") } } +/** `System.Windows.Markup.XamlReader.Parse` method */ class XamlReaderParseMethod extends Method, UnsafeDeserializer { XamlReaderParseMethod() { this.getDeclaringType() instanceof XamlReaderClass and @@ -310,6 +330,7 @@ class XamlReaderParseMethod extends Method, UnsafeDeserializer { } } +/** `System.Windows.Markup.XamlReader.Load` method */ class XamlReaderLoadMethod extends Method, UnsafeDeserializer { XamlReaderLoadMethod() { this.getDeclaringType() instanceof XamlReaderClass and @@ -318,6 +339,7 @@ class XamlReaderLoadMethod extends Method, UnsafeDeserializer { } } +/** `System.Windows.Markup.XamlReader.LoadAsync` method */ class XamlReaderLoadAsyncMethod extends Method, UnsafeDeserializer { XamlReaderLoadAsyncMethod() { this.getDeclaringType() instanceof XamlReaderClass and @@ -330,6 +352,7 @@ private class ProxyObjectClass extends Class { ProxyObjectClass() { this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject") } } +/** `Microsoft.Web.Design.Remote.ProxyObject.DecodeValue` method */ class ProxyObjectDecodeValueMethod extends Method, UnsafeDeserializer { ProxyObjectDecodeValueMethod() { this.getDeclaringType() instanceof ProxyObjectClass and @@ -337,6 +360,7 @@ class ProxyObjectDecodeValueMethod extends Method, UnsafeDeserializer { } } +/** `Microsoft.Web.Design.Remote.ProxyObject.DecodeSerializedObject` method */ class ProxyObjectDecodeSerializedObjectMethod extends Method, UnsafeDeserializer { ProxyObjectDecodeSerializedObjectMethod() { this.getDeclaringType() instanceof ProxyObjectClass and @@ -349,6 +373,7 @@ private class JaysonConverterClass extends Class { JaysonConverterClass() { this.hasQualifiedName("Sweet.Jayson.JaysonConverter") } } +/** `Sweet.Jayson.JaysonConverter.ToObject` method */ class JaysonConverterToObjectMethod extends Method, UnsafeDeserializer { JaysonConverterToObjectMethod() { this.getDeclaringType() instanceof JaysonConverterClass and @@ -364,6 +389,7 @@ private class ServiceStackTextJsonSerializerClass extends Class { } } +/** `ServiceStack.Text.JsonSerializer.DeserializeFromString` method */ class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and @@ -372,6 +398,7 @@ class ServiceStackTextJsonSerializerDeserializeFromStringMethod extends Method, } } +/** `ServiceStack.Text.JsonSerializer.DeserializeFromReader` method */ class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and @@ -380,6 +407,7 @@ class ServiceStackTextJsonSerializerDeserializeFromReaderMethod extends Method, } } +/** `ServiceStack.Text.JsonSerializer.DeserializeFromStream` method */ class ServiceStackTextJsonSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextJsonSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextJsonSerializerClass and @@ -395,6 +423,7 @@ private class ServiceStackTextTypeSerializerClass extends Class { } } +/** `ServiceStack.Text.TypeSerializer.DeserializeFromString` method */ class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and @@ -403,6 +432,7 @@ class ServiceStackTextTypeSerializerDeserializeFromStringMethod extends Method, } } +/** `ServiceStack.Text.TypeSerializer.DeserializeFromReader` method */ class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and @@ -411,6 +441,7 @@ class ServiceStackTextTypeSerializerDeserializeFromReaderMethod extends Method, } } +/** `ServiceStack.Text.TypeSerializer.DeserializeFromStream` method */ class ServiceStackTextTypeSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextTypeSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextTypeSerializerClass and @@ -424,6 +455,7 @@ private class ServiceStackTextCsvSerializerClass extends Class { ServiceStackTextCsvSerializerClass() { this.hasQualifiedName("ServiceStack.Text.CsvSerializer") } } +/** `ServiceStack.Text.CsvSerializer.DeserializeFromString` method */ class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and @@ -432,6 +464,7 @@ class ServiceStackTextCsvSerializerDeserializeFromStringMethod extends Method, U } } +/** `ServiceStack.Text.TypeSeriCsvSerializeralizer.DeserializeFromReader` method */ class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and @@ -440,6 +473,7 @@ class ServiceStackTextCsvSerializerDeserializeFromReaderMethod extends Method, U } } +/** `ServiceStack.Text.CsvSerializer.DeserializeFromStream` method */ class ServiceStackTextCsvSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextCsvSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextCsvSerializerClass and @@ -453,6 +487,7 @@ private class ServiceStackTextXmlSerializerClass extends Class { ServiceStackTextXmlSerializerClass() { this.hasQualifiedName("ServiceStack.Text.XmlSerializer") } } +/** `ServiceStack.Text.XmlSerializer.DeserializeFromString` method */ class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromStringMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and @@ -461,6 +496,7 @@ class ServiceStackTextXmlSerializerDeserializeFromStringMethod extends Method, U } } +/** `ServiceStack.Text.XmlSerializer.DeserializeFromReader` method */ class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromReaderMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and @@ -469,6 +505,7 @@ class ServiceStackTextXmlSerializerDeserializeFromReaderMethod extends Method, U } } +/** `ServiceStack.Text.XmlSerializer.DeserializeFromStream` method */ class ServiceStackTextXmlSerializerDeserializeFromStreamMethod extends Method, UnsafeDeserializer { ServiceStackTextXmlSerializerDeserializeFromStreamMethod() { this.getDeclaringType() instanceof ServiceStackTextXmlSerializerClass and From d85b1a2d5fc2c8bf0d79c09c9bd353958ddfaa77 Mon Sep 17 00:00:00 2001 From: thank_you Date: Wed, 28 Apr 2021 16:54:49 -0400 Subject: [PATCH 065/429] Replace recursive getAMember*() method --- .../ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 09777dd1037..ab702929855 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -27,7 +27,8 @@ private module NoSQL { API::moduleImport("pymongo") .getMember("MongoClient") .getReturn() - .getAMember*() + .getAMember() + .getAMember() .getMember(any(PyMongoMethods pyMongoMethod)) .getACall() } @@ -45,7 +46,8 @@ private module NoSQL { API::moduleImport("flask_pymongo") .getMember("PyMongo") .getReturn() - .getAMember*() + .getAMember() + .getAMember() .getMember(any(PyMongoFlaskMethods pyMongoFlaskMethod)) .getACall() } From 56dc4d886e0b86dd69865a75ed95e4430a24fddd Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 4 May 2021 19:11:59 -0400 Subject: [PATCH 066/429] Add comment on BsonObjectIdCall --- .../ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index ab702929855..20858e596c5 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -92,6 +92,10 @@ private module NoSQL { override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } } + /** ObjectId returns a string representing an id. + * If at any time ObjectId can't parse it's input (like when a tainted dict in passed in), + * then ObjectId will throw an error preventing the query from running. + */ private class BsonObjectIdCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { BsonObjectIdCall() { this = From c4a67e522cf6711e035a8b97cc640a7289d5b673 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 4 May 2021 19:29:31 -0400 Subject: [PATCH 067/429] Rewrite query to take into account MongoClient and subscript expressions A couple of notes with these changes: - Added TypeTracker pattern to handle subscript expressions. We've found that pymongo supports subscripts expressions when calling databases and collections. To resolve this, we implemented the TypeTracker pattern to catch those subscripts since CodeQL Python API modeling doesn't support subscript expressions. - After some research, we've discovered that MongoEngine and Flask-MongoEngine utilize MongoClient under-the-hood. This requires us to rewrite the query so that instead of querying these libraries with specific queries, we are instead going to query for usages of MongoClient since all of the libraries we are targeting utilizes MongoClient under-the-hood. --- .../semmle/python/frameworks/Stdlib.qll | 107 ++++++++++++------ 1 file changed, 71 insertions(+), 36 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 20858e596c5..05a8e1ac911 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -11,46 +11,80 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSQL { - private class PyMongoMethods extends string { - // These are all find-keyword relevant PyMongo collection level operation methods - PyMongoMethods() { + /** Gets a reference to a `MongoClient` DB. */ + private API::Node mongoClientInstance() { + result = API::moduleImport("pymongo").getMember("MongoClient").getReturn() or + result = + API::moduleImport("flask_mongoengine") + .getMember("MongoEngine") + .getReturn() + .getMember("get_db") + .getReturn() or + result = API::moduleImport("mongoengine").getMember("connect").getReturn() or + result = API::moduleImport("flask_pymongo").getMember("PyMongo").getReturn() + } + + /** Gets a reference to a `MongoClient` DB. */ + private DataFlow::LocalSourceNode mongoClientDB(DataFlow::TypeTracker t) { + t.start() and + ( + exists(SubscriptNode subscript | result.asCfgNode() = subscript | + subscript.getObject() = mongoClientInstance().getAUse().asCfgNode() + ) + or + result.(DataFlow::AttrRead).getObject() = mongoClientInstance().getAUse() + ) + or + exists(DataFlow::TypeTracker t2 | result = mongoClientDB(t2).track(t2, t)) + } + + /** Gets a reference to a `MongoClient` DB. */ + private DataFlow::Node mongoClientDB() { + mongoClientDB(DataFlow::TypeTracker::end()).flowsTo(result) + } + + /** Gets a reference to a `MongoClient` collection. */ + private DataFlow::LocalSourceNode mongoClientCollection(DataFlow::TypeTracker t) { + t.start() and + ( + exists(SubscriptNode subscript | result.asCfgNode() = subscript | + subscript.getObject() = mongoClientDB().asCfgNode() + ) + or + result.(DataFlow::AttrRead).getObject() = mongoClientDB() + ) + or + exists(DataFlow::TypeTracker t2 | result = mongoClientCollection(t2).track(t2, t)) + } + + /** Gets a reference to a `MongoClient` collection. */ + private DataFlow::Node mongoClientCollection() { + mongoClientCollection(DataFlow::TypeTracker::end()).flowsTo(result) + } + + /** This class represents names of find_* relevant MongoClient collection level operation methods. */ + private class MongoClientMethodNames extends string { + MongoClientMethodNames() { + // the find_one_or_404 method is only found in the Pymongo Flask library. this in [ "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", - "find_one_and_replace", "find_one_and_update" + "find_one_and_replace", "find_one_and_update", "find_one_or_404" ] } } - private class PyMongoClientCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - PyMongoClientCall() { - this = - API::moduleImport("pymongo") - .getMember("MongoClient") - .getReturn() - .getAMember() - .getAMember() - .getMember(any(PyMongoMethods pyMongoMethod)) - .getACall() - } - - override DataFlow::Node getQuery() { result = this.getArg(0) } + /** Gets a reference to a `MongoClient` Collection method. */ + DataFlow::Node mongoClientMethod() { + result.(DataFlow::AttrRead).getAttributeName() instanceof MongoClientMethodNames and + ( + result.(DataFlow::AttrRead).getObject() = mongoClientCollection() or + result.(DataFlow::AttrRead) = mongoClientCollection() + ) } - private class PyMongoFlaskMethods extends string { - PyMongoFlaskMethods() { this in ["find_one_or_404", any(PyMongoMethods pyMongoMethod)] } - } - - private class PyMongoFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - PyMongoFlaskCall() { - this = - API::moduleImport("flask_pymongo") - .getMember("PyMongo") - .getReturn() - .getAMember() - .getAMember() - .getMember(any(PyMongoFlaskMethods pyMongoFlaskMethod)) - .getACall() - } + /** Gets a reference to a `MongoClient` call */ + private class MongoClientCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + MongoClientCall() { this.getFunction() = mongoClientMethod() } override DataFlow::Node getQuery() { result = this.getArg(0) } } @@ -92,10 +126,11 @@ private module NoSQL { override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } } - /** ObjectId returns a string representing an id. - * If at any time ObjectId can't parse it's input (like when a tainted dict in passed in), - * then ObjectId will throw an error preventing the query from running. - */ + /** + * ObjectId returns a string representing an id. + * If at any time ObjectId can't parse it's input (like when a tainted dict in passed in), + * then ObjectId will throw an error preventing the query from running. + */ private class BsonObjectIdCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { BsonObjectIdCall() { this = From 1d36aa6649b6ac3ed9a28e8649f893a5944478b9 Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 14:30:50 -0400 Subject: [PATCH 068/429] Add additional querying for mongoengine Document subclassing After further research, it was discovered that Flask-Mongoengine has multiple ways of allowing a developer to call the Document class. One way is by directly importing the Document class from the module. Another approach is to get the Document class via a mongoengine instance. The update to this query checks for cases where the developer gets the Document class via the MongoEngine instance. Other misc changes include setting the various predicates to private. --- .../semmle/python/frameworks/Stdlib.qll | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 05a8e1ac911..9339780b06c 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -20,7 +20,10 @@ private module NoSQL { .getReturn() .getMember("get_db") .getReturn() or - result = API::moduleImport("mongoengine").getMember("connect").getReturn() or + result = + API::moduleImport(["mongoengine", "mongoengine.connection"]) + .getMember(["get_db", "connect"]) + .getReturn() or result = API::moduleImport("flask_pymongo").getMember("PyMongo").getReturn() } @@ -65,7 +68,7 @@ private module NoSQL { /** This class represents names of find_* relevant MongoClient collection level operation methods. */ private class MongoClientMethodNames extends string { MongoClientMethodNames() { - // the find_one_or_404 method is only found in the Pymongo Flask library. + // the find_one_or_404 method is only found in the Pymongo Flask library. this in [ "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", "find_one_and_replace", "find_one_and_update", "find_one_or_404" @@ -74,7 +77,7 @@ private module NoSQL { } /** Gets a reference to a `MongoClient` Collection method. */ - DataFlow::Node mongoClientMethod() { + private DataFlow::Node mongoClientMethod() { result.(DataFlow::AttrRead).getAttributeName() instanceof MongoClientMethodNames and ( result.(DataFlow::AttrRead).getObject() = mongoClientCollection() or @@ -102,8 +105,8 @@ private module NoSQL { override DataFlow::Node getQuery() { result = this.getArgByName(_) } } - private class MongoEngineObjectsFlaskCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - MongoEngineObjectsFlaskCall() { + private class FlaskMongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + FlaskMongoEngineObjectsCall() { this = API::moduleImport("flask_mongoengine") .getMember("MongoEngine") @@ -117,6 +120,46 @@ private module NoSQL { override DataFlow::Node getQuery() { result = this.getArgByName(_) } } + private DataFlow::Node flaskMongoEngineInstance() { + result = API::moduleImport("flask_mongoengine").getMember("MongoEngine").getReturn().getAUse() + } + + /** + * A MongoEngine.Document subclass which represents a single MongoDB table. + */ + private class FlaskMongoEngineDocumentClass extends ClassValue { + FlaskMongoEngineDocumentClass() { + this.getASuperType().getName() = "Document" and + exists(AttrNode documentClass | + documentClass.getName() = "Document" and + documentClass.getObject() = flaskMongoEngineInstance().asCfgNode() and + // This is super hacky. It checks to see if the class is a subclass of a flaskMongoEngineInstance.Document + this.getASuperType() + .getAReference() + .getNode() + .(ClassExpr) + .contains(documentClass.getNode().getObject()) + ) + } + } + + private class FlaskMongoEngineDocumentSubclassInstanceCall extends DataFlow::CallCfgNode, + NoSQLQuery::Range { + FlaskMongoEngineDocumentSubclassInstanceCall() { + exists( + DataFlow::CallCfgNode objectsCall, + FlaskMongoEngineDocumentClass flaskMongoEngineDocumentClass + | + objectsCall.getFunction().asExpr().(Attribute).getObject().getAFlowNode() = + flaskMongoEngineDocumentClass.getAReference() and + objectsCall.asCfgNode().(CallNode).getNode().getFunc().(Attribute).getName() = "objects" and + this = objectsCall + ) + } + + override DataFlow::Node getQuery() { result = this.getArgByName(_) } + } + private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { MongoSanitizerCall() { this = From 7693d696cc9f1c208cbcb39c2c3bde53253a329b Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 14:36:02 -0400 Subject: [PATCH 069/429] Add additional query tests To ensure that this query works against numerous usages of libraries such as PyMongo, Flask PyMongo, Mongoengine, and Flask Mongoengine, I've added a variety of query tests to test against. These tests deal with scenarious such as: - Subscript expressions - Mongoengine instances and Document subclasses - Mongoengine connection usage - And more... --- .../CWE-943/flask_mongoengine_get_db_bad.py | 31 +++++++++++++++++ .../CWE-943/flask_mongoengine_get_db_good.py | 33 +++++++++++++++++++ .../CWE-943/mongoclient_subscript_bad.py | 29 ++++++++++++++++ .../CWE-943/mongoclient_subscript_good.py | 31 +++++++++++++++++ ...goengine-flask-db-document-subclass-bad.py | 29 ++++++++++++++++ ...oengine-flask-db-document-subclass-good.py | 31 +++++++++++++++++ .../CWE-943/mongoengine_connect_bad.py | 29 ++++++++++++++++ .../CWE-943/mongoengine_connect_good.py | 31 +++++++++++++++++ .../mongoengine_connect_via_connection_bad.py | 30 +++++++++++++++++ ...mongoengine_connect_via_connection_good.py | 32 ++++++++++++++++++ .../CWE-943/mongoengine_get_db_bad.py | 29 ++++++++++++++++ .../CWE-943/mongoengine_get_db_good.py | 31 +++++++++++++++++ .../mongoengine_get_db_via_connection_bad.py | 30 +++++++++++++++++ .../mongoengine_get_db_via_connection_good.py | 32 ++++++++++++++++++ 14 files changed, 428 insertions(+) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py new file mode 100644 index 00000000000..b4013ab1950 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py @@ -0,0 +1,31 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +import json + +app = Flask(__name__) +db = MongoEngine(app) +db.init_app(app) + + +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsanitized_search = request.args['search'] + json_search = json.loads(unsanitized_search) + + retrieved_db = db.get_db() + result = retrieved_db["Movie"].find_one_or_404({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py new file mode 100644 index 00000000000..1cc57a2b364 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py @@ -0,0 +1,33 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) +db = MongoEngine(app) +db.init_app(app) + + +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsanitized_search = request.args['search'] + json_search = json.loads(unsanitized_search) + safe_search = sanitize(json_search) + + retrieved_db = db.get_db() + result = retrieved_db["Movie"].find_one_or_404({'name': safe_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py new file mode 100644 index 00000000000..14f1177a023 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py @@ -0,0 +1,29 @@ +from flask import Flask, request +import mongoengine as me +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.connect('mydb') + data = db['mydb']['movie'].find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py new file mode 100644 index 00000000000..1d1aad89780 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py @@ -0,0 +1,31 @@ +from flask import Flask, request +import mongoengine as me +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.connect('mydb') + data = db['mydb']['movie'].find({'name': safe_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py new file mode 100644 index 00000000000..e8f05bba707 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py @@ -0,0 +1,29 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +import json + +app = Flask(__name__) +app.config.from_pyfile('the-config.cfg') +db = MongoEngine(app) + +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + data = Movie.objects(__raw__=json_search) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py new file mode 100644 index 00000000000..7fd0e927155 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py @@ -0,0 +1,31 @@ +from flask import Flask, request +from flask_mongoengine import MongoEngine +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) +app.config.from_pyfile('the-config.cfg') +db = MongoEngine(app) + +class Movie(db.Document): + title = db.StringField(required=True) + year = db.IntField() + rated = db.StringField() + director = db.StringField() + actors = db.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + data = Movie.objects(__raw__=safe_search) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py new file mode 100644 index 00000000000..7d50fc8bd44 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py @@ -0,0 +1,29 @@ +from flask import Flask, request +import mongoengine as me +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.connect('mydb') + data = db.mydb.movie.find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py new file mode 100644 index 00000000000..0dfaac547dd --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py @@ -0,0 +1,31 @@ +from flask import Flask, request +import mongoengine as me +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.connect('mydb') + data = db.mydb.movie.find({'name': safe_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py new file mode 100644 index 00000000000..10d9e17523f --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py @@ -0,0 +1,30 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = connect('mydb') + data = db.mydb.movie.find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py new file mode 100644 index 00000000000..d00d82894de --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py @@ -0,0 +1,32 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = connect('mydb') + data = db.mydb.movie.find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py new file mode 100644 index 00000000000..5722881fc3e --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py @@ -0,0 +1,29 @@ +from flask import Flask, request +import mongoengine as me +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.get_db() + data = db.movie.find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py new file mode 100644 index 00000000000..7c4aad77f8f --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py @@ -0,0 +1,31 @@ +from flask import Flask, request +import mongoengine as me +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.get_db() + data = db.movie.find({'name': safe_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py new file mode 100644 index 00000000000..3fe927e113a --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py @@ -0,0 +1,30 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = get_db() + data = db.movie.find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py new file mode 100644 index 00000000000..bc5f48c037e --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py @@ -0,0 +1,32 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + year = me.IntField() + rated = me.StringField() + director = me.StringField() + actors = me.ListField() + + +Movie(title='aa').save() +Movie(title='bb').save() + + +@app.route("/") +def home_page(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = get_db() + data = db.movie.find({'name': safe_search}) + +# if __name__ == "__main__": +# app.run(debug=True) From 8f8eff231aa30e1741f6d659ad0e6ced56cd4d03 Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 15:08:48 -0400 Subject: [PATCH 070/429] Fix comment description of predicate --- python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 9339780b06c..4d8efefb941 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -11,7 +11,7 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSQL { - /** Gets a reference to a `MongoClient` DB. */ + /** Gets a reference to a `MongoClient` instance. */ private API::Node mongoClientInstance() { result = API::moduleImport("pymongo").getMember("MongoClient").getReturn() or result = From 9a44020af3ff8a979d6bcb24ad5fa9c1c0592d8d Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 15:13:30 -0400 Subject: [PATCH 071/429] Rename StdLib.qll file to NoSQL.qll file It makes more sense to have this file represent just the NoSQL module --- .../semmle/python/frameworks/{Stdlib.qll => NoSQL.qll} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/ql/src/experimental/semmle/python/frameworks/{Stdlib.qll => NoSQL.qll} (100%) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll similarity index 100% rename from python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll rename to python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll From 83f087023130e34d80a8d3bdacace3c7e32010bb Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 15:13:56 -0400 Subject: [PATCH 072/429] Update file path of module --- python/ql/src/experimental/semmle/python/Frameworks.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index ca1dd04e57d..116a6b65046 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -2,4 +2,4 @@ * Helper file that imports all framework modeling. */ -private import experimental.semmle.python.frameworks.Stdlib +private import experimental.semmle.python.frameworks.NoSQL From aa24c689bc71932800617bf2cfa695020e7f735a Mon Sep 17 00:00:00 2001 From: thank_you Date: Fri, 7 May 2021 15:17:01 -0400 Subject: [PATCH 073/429] Add back accidentally deleted StdLib.qll file --- .../ql/src/experimental/semmle/python/Frameworks.qll | 1 + .../experimental/semmle/python/frameworks/StdLib.qll | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 python/ql/src/experimental/semmle/python/frameworks/StdLib.qll diff --git a/python/ql/src/experimental/semmle/python/Frameworks.qll b/python/ql/src/experimental/semmle/python/Frameworks.qll index 116a6b65046..49b16d9443a 100644 --- a/python/ql/src/experimental/semmle/python/Frameworks.qll +++ b/python/ql/src/experimental/semmle/python/Frameworks.qll @@ -2,4 +2,5 @@ * Helper file that imports all framework modeling. */ +private import experimental.semmle.python.frameworks.Stdlib private import experimental.semmle.python.frameworks.NoSQL diff --git a/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll b/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll new file mode 100644 index 00000000000..420caf0d73b --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll @@ -0,0 +1,11 @@ +/** + * Provides classes modeling security-relevant aspects of the standard libraries. + * Note: some modeling is done internally in the dataflow/taint tracking implementation. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.RemoteFlowSources +private import experimental.semmle.python.Concepts +private import semmle.python.ApiGraphs From 65c6f1976ae4040f206cdcc33764b708a52a5c50 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 7 May 2021 23:00:08 +0200 Subject: [PATCH 074/429] Rename mongoengine-flask-db-document-subclass --- ...class-bad.py => mongoengine_flask_db_document_subclass_bad.py} | 0 ...ass-good.py => mongoengine_flask_db_document_subclass_good.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine-flask-db-document-subclass-bad.py => mongoengine_flask_db_document_subclass_bad.py} (100%) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine-flask-db-document-subclass-good.py => mongoengine_flask_db_document_subclass_good.py} (100%) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine-flask-db-document-subclass-good.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py From e7bdc73420e3d6ead5bd5ce7087e2da3d30a8d11 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 7 May 2021 23:00:21 +0200 Subject: [PATCH 075/429] Update .expected --- .../Security/CWE-943/NoSQLInjection.expected | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 9135d887e31..c101db1f810 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -3,6 +3,13 @@ edges | flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | | flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | | flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | +| flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | +| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:26:30:26:47 | ControlFlowNode for unsanitized_search | | flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | | flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | | flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:26:30:26:42 | ControlFlowNode for unsafe_search | @@ -13,10 +20,52 @@ edges | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | +| mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | +| mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | +| mongoclient_subscript_good.py:23:21:23:27 | ControlFlowNode for request | mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoclient_subscript_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | | mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | | mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | | mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | +| mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | +| mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | +| mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | +| mongoengine_connect_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | +| mongoengine_get_db_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | +| mongoengine_get_db_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | | mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | | mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | | mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | @@ -33,6 +82,15 @@ nodes | flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:26:30:26:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | | flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -46,11 +104,65 @@ nodes | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoclient_subscript_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoclient_subscript_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_get_db_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_get_db_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -66,6 +178,13 @@ nodes | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | #select | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | user-provided value | +| mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | +| mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | This | mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | +| mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | +| mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From 0fc044dfd574729cb447b4fadc5cece1cc1b5653 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Fri, 7 May 2021 23:03:23 +0200 Subject: [PATCH 076/429] Checkout Stdlib.qll --- .../experimental/semmle/python/frameworks/Stdlib.qll | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll new file mode 100644 index 00000000000..420caf0d73b --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -0,0 +1,11 @@ +/** + * Provides classes modeling security-relevant aspects of the standard libraries. + * Note: some modeling is done internally in the dataflow/taint tracking implementation. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.RemoteFlowSources +private import experimental.semmle.python.Concepts +private import semmle.python.ApiGraphs From 67bc576e30c5029164a0511abeb7af78d5ead982 Mon Sep 17 00:00:00 2001 From: "${sleep,5}" <52643283+mrthankyou@users.noreply.github.com> Date: Fri, 7 May 2021 17:37:02 -0400 Subject: [PATCH 077/429] Delete StdLib.qll --- .../experimental/semmle/python/frameworks/StdLib.qll | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 python/ql/src/experimental/semmle/python/frameworks/StdLib.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll b/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll deleted file mode 100644 index 420caf0d73b..00000000000 --- a/python/ql/src/experimental/semmle/python/frameworks/StdLib.qll +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Provides classes modeling security-relevant aspects of the standard libraries. - * Note: some modeling is done internally in the dataflow/taint tracking implementation. - */ - -private import python -private import semmle.python.dataflow.new.DataFlow -private import semmle.python.dataflow.new.TaintTracking -private import semmle.python.dataflow.new.RemoteFlowSources -private import experimental.semmle.python.Concepts -private import semmle.python.ApiGraphs From 07c3e224280046e26ee0c0c978fd71e2ff79c20c Mon Sep 17 00:00:00 2001 From: thank_you Date: Sun, 9 May 2021 19:23:52 -0400 Subject: [PATCH 078/429] Fix method name to match flask_mongoengine library --- .../Security/CWE-943/flask_mongoengine_get_db_bad.py | 2 +- .../Security/CWE-943/flask_mongoengine_get_db_good.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py index b4013ab1950..df8dde96f3e 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py @@ -25,7 +25,7 @@ def home_page(): json_search = json.loads(unsanitized_search) retrieved_db = db.get_db() - result = retrieved_db["Movie"].find_one_or_404({'name': json_search}) + result = retrieved_db["Movie"].find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py index 1cc57a2b364..ce5fa89dc7f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py @@ -27,7 +27,7 @@ def home_page(): safe_search = sanitize(json_search) retrieved_db = db.get_db() - result = retrieved_db["Movie"].find_one_or_404({'name': safe_search}) + result = retrieved_db["Movie"].find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) From 0238e51c1067754ead8b5daaaa1820b59991decd Mon Sep 17 00:00:00 2001 From: thank_you Date: Sun, 9 May 2021 19:42:40 -0400 Subject: [PATCH 079/429] Add checks for EmbeddedDocument classes Mongoengine supports EmbeddedDocument documents. We should check for this in our query. --- .../experimental/semmle/python/frameworks/NoSQL.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll index 4d8efefb941..94d327d7901 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll @@ -96,7 +96,7 @@ private module NoSQL { MongoEngineObjectsCall() { this = API::moduleImport("mongoengine") - .getMember("Document") + .getMember(["Document", "EmbeddedDocument"]) .getASubclass() .getMember("objects") .getACall() @@ -111,7 +111,7 @@ private module NoSQL { API::moduleImport("flask_mongoengine") .getMember("MongoEngine") .getReturn() - .getMember("Document") + .getMember(["Document", "EmbeddedDocument"]) .getASubclass() .getMember("objects") .getACall() @@ -125,13 +125,13 @@ private module NoSQL { } /** - * A MongoEngine.Document subclass which represents a single MongoDB table. + * A MongoEngine.Document or MongoEngine.EmbeddedDocument subclass which represents a MongoDB document. */ private class FlaskMongoEngineDocumentClass extends ClassValue { FlaskMongoEngineDocumentClass() { - this.getASuperType().getName() = "Document" and + this.getASuperType().getName() in ["Document", "EmbeddedDocument"] and exists(AttrNode documentClass | - documentClass.getName() = "Document" and + documentClass.getName() in ["Document", "EmbeddedDocument"] and documentClass.getObject() = flaskMongoEngineInstance().asCfgNode() and // This is super hacky. It checks to see if the class is a subclass of a flaskMongoEngineInstance.Document this.getASuperType() From 3e25b14a680b71ee994736dd11542ecbbe54be72 Mon Sep 17 00:00:00 2001 From: thank_you Date: Tue, 11 May 2021 20:07:09 -0400 Subject: [PATCH 080/429] Update NoSQLInjection.expected --- .../query-tests/Security/CWE-943/NoSQLInjection.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index c101db1f810..fd02261ed90 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -6,7 +6,7 @@ edges | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | | flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | | flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | +| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | | flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | | flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | | flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:26:30:26:47 | ControlFlowNode for unsanitized_search | @@ -86,7 +86,7 @@ nodes | flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -178,7 +178,7 @@ nodes | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | #select | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:28:52:28:72 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | user-provided value | | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | From 6bed8594f23e7c1b72fa5722d9df0634c7763053 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 15 Jun 2021 16:27:32 +0200 Subject: [PATCH 081/429] Match sanitizer inputs' naming --- python/ql/src/experimental/semmle/python/Concepts.qll | 4 ++-- python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll | 4 ++-- .../semmle/python/security/injection/NoSQLInjection.qll | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 07e9f21e33e..2134b32e60a 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -163,7 +163,7 @@ class NoSQLQuery extends DataFlow::Node { module NoSQLSanitizer { abstract class Range extends DataFlow::Node { - abstract DataFlow::Node getSanitizerNode(); + abstract DataFlow::Node getAnInput(); } } @@ -172,5 +172,5 @@ class NoSQLSanitizer extends DataFlow::Node { NoSQLSanitizer() { this = range } - DataFlow::Node getSanitizerNode() { result = range.getSanitizerNode() } + DataFlow::Node getAnInput() { result = range.getAnInput() } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll index 94d327d7901..6561db67f9a 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll @@ -166,7 +166,7 @@ private module NoSQL { API::moduleImport("mongosanitizer").getMember("sanitizer").getMember("sanitize").getACall() } - override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } + override DataFlow::Node getAnInput() { result = this.getArg(0) } } /** @@ -182,6 +182,6 @@ private module NoSQL { .getACall() } - override DataFlow::Node getSanitizerNode() { result = this.getArg(0) } + override DataFlow::Node getAnInput() { result = this.getArg(0) } } } diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 27109bb3439..8217f370af7 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -42,7 +42,7 @@ class RFSToDictConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof DataToDictSink } override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput() } } @@ -54,7 +54,7 @@ class FromDataDictToSink extends TaintTracking2::Configuration { override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQuery() } override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer = any(NoSQLSanitizer noSQLSanitizer).getSanitizerNode() + sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput() } } From e61cf9a58d5a6a8a420e37479d2765490336b05d Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 15 Jun 2021 19:32:02 +0200 Subject: [PATCH 082/429] Simplify tests --- .../query-tests/Security/CWE-943/flask_mongoengine_bad.py | 7 +------ .../Security/CWE-943/flask_mongoengine_get_db_bad.py | 7 +------ .../Security/CWE-943/flask_mongoengine_get_db_good.py | 7 +------ .../query-tests/Security/CWE-943/flask_mongoengine_good.py | 7 +------ .../Security/CWE-943/mongoclient_subscript_bad.py | 7 +------ .../Security/CWE-943/mongoclient_subscript_good.py | 7 +------ .../query-tests/Security/CWE-943/mongoengine_bad.py | 7 +------ .../Security/CWE-943/mongoengine_connect_bad.py | 7 +------ .../Security/CWE-943/mongoengine_connect_good.py | 7 +------ .../CWE-943/mongoengine_connect_via_connection_bad.py | 7 +------ .../CWE-943/mongoengine_connect_via_connection_good.py | 7 +------ .../CWE-943/mongoengine_flask_db_document_subclass_bad.py | 7 +------ .../CWE-943/mongoengine_flask_db_document_subclass_good.py | 7 +------ .../query-tests/Security/CWE-943/mongoengine_get_db_bad.py | 7 +------ .../Security/CWE-943/mongoengine_get_db_good.py | 7 +------ .../CWE-943/mongoengine_get_db_via_connection_bad.py | 7 +------ .../CWE-943/mongoengine_get_db_via_connection_good.py | 7 +------ .../query-tests/Security/CWE-943/mongoengine_good.py | 7 +------ 18 files changed, 18 insertions(+), 108 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py index b7dca69f70b..8f9da2d6d72 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -9,14 +9,9 @@ db.init_app(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py index df8dde96f3e..0becf217e53 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py @@ -9,14 +9,9 @@ db.init_app(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py index ce5fa89dc7f..e1d4ea7d778 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py @@ -10,14 +10,9 @@ db.init_app(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index 89f6d49a3d1..5b34de49781 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -10,14 +10,9 @@ db.init_app(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py index 14f1177a023..cc1fd7ce59a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py @@ -7,14 +7,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py index 1d1aad89780..8a5bed832c6 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py index c48f7bb9ddb..95467393541 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py @@ -7,14 +7,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py index 7d50fc8bd44..8d6a0c30d52 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py @@ -7,14 +7,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py index 0dfaac547dd..93109deeaf9 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py index 10d9e17523f..167eddeb5e9 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py index d00d82894de..0283bfdd57a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py @@ -9,14 +9,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py index e8f05bba707..f55f3270f47 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py @@ -8,14 +8,9 @@ db = MongoEngine(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py index 7fd0e927155..c0a03d718aa 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py @@ -9,14 +9,9 @@ db = MongoEngine(app) class Movie(db.Document): title = db.StringField(required=True) - year = db.IntField() - rated = db.StringField() - director = db.StringField() - actors = db.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py index 5722881fc3e..8b1d8ebb6fb 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py @@ -7,14 +7,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py index 7c4aad77f8f..08c43b4d209 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py index 3fe927e113a..76b32a69572 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py index bc5f48c037e..9ac27c8c54a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py @@ -9,14 +9,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py index ac7937195e8..c852d550464 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -8,14 +8,9 @@ app = Flask(__name__) class Movie(me.Document): title = me.StringField(required=True) - year = me.IntField() - rated = me.StringField() - director = me.StringField() - actors = me.ListField() -Movie(title='aa').save() -Movie(title='bb').save() +Movie(title='test').save() @app.route("/") From 5123b8f4e34e343e6a5d3ffb058ce854016069d3 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 15 Jun 2021 20:29:33 +0200 Subject: [PATCH 083/429] Update .expected --- .../Security/CWE-943/NoSQLInjection.expected | 306 +++++++++--------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index fd02261ed90..dd247bc9206 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,18 +1,18 @@ edges -| flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | -| flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | -| flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | -| flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:26:30:26:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:26:30:26:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | +| flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | +| flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | +| flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:20:26:20:32 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:30:21:47 | ControlFlowNode for unsanitized_search | +| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | | flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | @@ -20,55 +20,55 @@ edges | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | -| mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | -| mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | -| mongoclient_subscript_good.py:23:21:23:27 | ControlFlowNode for request | mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoclient_subscript_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | -| mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | -| mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | -| mongoengine_connect_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | -| mongoengine_connect_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | -| mongoengine_get_db_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | -| mongoengine_get_db_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | -| mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | mongoengine_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | +| mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | +| mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | +| mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | +| mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | +| mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | @@ -77,24 +77,24 @@ edges | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | nodes -| flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_bad.py:24:26:24:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_bad.py:24:26:24:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:24:26:24:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:25:30:25:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:25:26:25:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_good.py:25:26:25:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:25:26:25:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:26:30:26:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_good.py:25:21:25:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_good.py:25:21:25:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:25:21:25:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:26:30:26:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:20:26:20:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:21:30:21:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | +| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -104,69 +104,69 @@ nodes | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoclient_subscript_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoclient_subscript_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoclient_subscript_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoclient_subscript_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoclient_subscript_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoclient_subscript_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoclient_subscript_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_connect_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_connect_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_bad.py:22:21:22:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_bad.py:22:21:22:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:23:30:23:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_get_db_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_via_connection_bad.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_bad.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_get_db_via_connection_good.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_via_connection_good.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_good.py:24:21:24:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:25:30:25:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_good.py:23:21:23:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:23:21:23:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:23:21:23:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:24:30:24:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_flask_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -177,14 +177,14 @@ nodes | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | #select -| flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:27:36:27:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:28:41:28:61 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:24:26:24:32 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | user-provided value | | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | user-provided value | -| mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:26:37:26:57 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:25:34:25:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:26:31:26:51 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:27:31:27:51 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | -| mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_flask_db_document_subclass_bad.py:26:34:26:44 | ControlFlowNode for json_search | This | mongoengine_flask_db_document_subclass_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | -| mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:26:26:26:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:22:21:22:27 | ControlFlowNode for request | user-provided value | -| mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:27:26:27:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:23:21:23:27 | ControlFlowNode for request | user-provided value | +| mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | This | mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From 81505fbd76d4add27d7fb6e2146473b3e77387f5 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 16 Jun 2021 23:18:38 +0200 Subject: [PATCH 084/429] Normalize tests --- .../Security/CWE-943/flask_mongoengine_bad.py | 25 ----------------- ...k_mongoengine_db_document_subclass_bad.py} | 0 ..._mongoengine_db_document_subclass_good.py} | 0 .../CWE-943/flask_mongoengine_get_db_bad.py | 8 +++--- .../CWE-943/flask_mongoengine_get_db_good.py | 8 +++--- .../CWE-943/flask_mongoengine_good.py | 27 ------------------- .../Security/CWE-943/flask_pymongo_bad.py | 6 ++--- .../Security/CWE-943/flask_pymongo_good.py | 2 +- .../CWE-943/mongoclient_subscript_bad.py | 2 +- .../CWE-943/mongoclient_subscript_good.py | 2 +- .../CWE-943/mongoengine_connect_bad.py | 2 +- .../CWE-943/mongoengine_connect_good.py | 2 +- .../mongoengine_connect_via_connection_bad.py | 2 +- ...mongoengine_connect_via_connection_good.py | 2 +- ...y => mongoengine_document_subclass_bad.py} | 0 ... => mongoengine_document_subclass_good.py} | 0 .../Security/CWE-943/pymongo_bad.py | 2 +- .../Security/CWE-943/pymongo_good.py | 2 +- 18 files changed, 20 insertions(+), 72 deletions(-) delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine_flask_db_document_subclass_bad.py => flask_mongoengine_db_document_subclass_bad.py} (100%) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine_flask_db_document_subclass_good.py => flask_mongoengine_db_document_subclass_good.py} (100%) delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine_bad.py => mongoengine_document_subclass_bad.py} (100%) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoengine_good.py => mongoengine_document_subclass_good.py} (100%) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py deleted file mode 100644 index 8f9da2d6d72..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py +++ /dev/null @@ -1,25 +0,0 @@ -from flask import Flask, request -from flask_mongoengine import MongoEngine -import json - -app = Flask(__name__) -db = MongoEngine(app) -db.init_app(app) - - -class Movie(db.Document): - title = db.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsanitized_search = request.args['search'] - json_search = json.loads(unsanitized_search) - - result = Movie.objects(__raw__=json_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_flask_db_document_subclass_good.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py index 0becf217e53..468e1d865a7 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py @@ -3,8 +3,8 @@ from flask_mongoengine import MongoEngine import json app = Flask(__name__) +app.config.from_pyfile('the-config.cfg') db = MongoEngine(app) -db.init_app(app) class Movie(db.Document): @@ -16,11 +16,11 @@ Movie(title='test').save() @app.route("/") def home_page(): - unsanitized_search = request.args['search'] - json_search = json.loads(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) retrieved_db = db.get_db() - result = retrieved_db["Movie"].find({'name': json_search}) + data = retrieved_db["Movie"].find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py index e1d4ea7d778..5837eaa2d58 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py @@ -4,8 +4,8 @@ from mongosanitizer.sanitizer import sanitize import json app = Flask(__name__) +app.config.from_pyfile('the-config.cfg') db = MongoEngine(app) -db.init_app(app) class Movie(db.Document): @@ -17,12 +17,12 @@ Movie(title='test').save() @app.route("/") def home_page(): - unsanitized_search = request.args['search'] - json_search = json.loads(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) retrieved_db = db.get_db() - result = retrieved_db["Movie"].find({'name': safe_search}) + data = retrieved_db["Movie"].find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py deleted file mode 100644 index 5b34de49781..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask import Flask, request -from flask_mongoengine import MongoEngine -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) -db = MongoEngine(app) -db.init_app(app) - - -class Movie(db.Document): - title = db.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - result = Movie.objects(__raw__=safe_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py index 421e2d65a9e..93c570fbe58 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py @@ -8,10 +8,10 @@ mongo = PyMongo(app) @app.route("/") def home_page(): - unsanitized_search = request.args['search'] - json_search = json.loads(unsanitized_search) + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) - result = mongo.db.user.find({'name': json_search}) + data = mongo.db.user.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py index 72907b6ba43..29af42d8536 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py @@ -13,7 +13,7 @@ def home_page(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - result = mongo.db.user.find({'name': safe_search}) + data = mongo.db.user.find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py index cc1fd7ce59a..96e08418b24 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py @@ -18,7 +18,7 @@ def home_page(): json_search = json.loads(unsafe_search) db = me.connect('mydb') - data = db['mydb']['movie'].find({'name': json_search}) + data = db['movie'].find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py index 8a5bed832c6..e9be8dd3e3c 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py @@ -20,7 +20,7 @@ def home_page(): safe_search = sanitize(json_search) db = me.connect('mydb') - data = db['mydb']['movie'].find({'name': safe_search}) + data = db['movie'].find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py index 8d6a0c30d52..1443f72720d 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py @@ -18,7 +18,7 @@ def home_page(): json_search = json.loads(unsafe_search) db = me.connect('mydb') - data = db.mydb.movie.find({'name': json_search}) + data = db.movie.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py index 93109deeaf9..219503a213a 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py @@ -20,7 +20,7 @@ def home_page(): safe_search = sanitize(json_search) db = me.connect('mydb') - data = db.mydb.movie.find({'name': safe_search}) + data = db.movie.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py index 167eddeb5e9..398199bc0cd 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py @@ -19,7 +19,7 @@ def home_page(): json_search = json.loads(unsafe_search) db = connect('mydb') - data = db.mydb.movie.find({'name': json_search}) + data = db.movie.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py index 0283bfdd57a..51b801468ce 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py @@ -21,7 +21,7 @@ def home_page(): safe_search = sanitize(json_search) db = connect('mydb') - data = db.mydb.movie.find({'name': json_search}) + data = db.movie.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py index e280f90a9f9..e0fc3514d73 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py @@ -11,7 +11,7 @@ def home_page(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - result = client.db.collection.find_one({'data': json_search}) + data = client.db.collection.find_one({'data': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py index f6a113203f9..0e52609fd7d 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py @@ -13,7 +13,7 @@ def home_page(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - result = client.db.collection.find_one({'data': safe_search}) + data = client.db.collection.find_one({'data': safe_search}) # if __name__ == "__main__": # app.run(debug=True) From 5c7229c715496d479104bdec8f957a52bf585159 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 16 Jun 2021 23:19:05 +0200 Subject: [PATCH 085/429] Optimize Type Tracking stuff --- .../semmle/python/frameworks/NoSQL.qll | 174 +++++++----------- 1 file changed, 64 insertions(+), 110 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll index 6561db67f9a..2b6fbb1f752 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll @@ -11,64 +11,76 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSQL { - /** Gets a reference to a `MongoClient` instance. */ - private API::Node mongoClientInstance() { - result = API::moduleImport("pymongo").getMember("MongoClient").getReturn() or - result = - API::moduleImport("flask_mongoengine") - .getMember("MongoEngine") - .getReturn() - .getMember("get_db") - .getReturn() or - result = - API::moduleImport(["mongoengine", "mongoengine.connection"]) - .getMember(["get_db", "connect"]) - .getReturn() or + /** API Nodes returning `Mongo` instances. */ + private API::Node pyMongo() { + result = API::moduleImport("pymongo").getMember("MongoClient").getReturn() + } + + private API::Node flask_PyMongo() { result = API::moduleImport("flask_pymongo").getMember("PyMongo").getReturn() } - /** Gets a reference to a `MongoClient` DB. */ - private DataFlow::LocalSourceNode mongoClientDB(DataFlow::TypeTracker t) { + private API::Node mongoEngine() { result = API::moduleImport("mongoengine") } + + private API::Node flask_MongoEngine() { + result = API::moduleImport("flask_mongoengine").getMember("MongoEngine").getReturn() + } + + /** Gets a reference to a initialized `Mongo` instance. */ + private API::Node mongoInstance() { + result = pyMongo() or + result = flask_PyMongo() + } + + /** Gets a reference to a initialized `Mongo` DB instance. */ + private API::Node mongoDBInstance() { + result = mongoEngine().getMember(["get_db", "connect"]).getReturn() or + result = mongoEngine().getMember("connection").getMember(["get_db", "connect"]).getReturn() or + result = flask_MongoEngine().getMember("get_db").getReturn() + } + + /** Gets a reference to a `Mongo` DB use. */ + private DataFlow::LocalSourceNode mongoDB(DataFlow::TypeTracker t) { + t.start() and + ( + exists(SubscriptNode subscript | + subscript.getObject() = mongoInstance().getAUse().asCfgNode() and + result.asCfgNode() = subscript + ) + or + result.(DataFlow::AttrRead).getObject() = mongoInstance().getAUse() + or + result = mongoDBInstance().getAUse() + ) + or + exists(DataFlow::TypeTracker t2 | result = mongoDB(t2).track(t2, t)) + } + + /** Gets a reference to a `Mongo` DB use. */ + private DataFlow::Node mongoDB() { mongoDB(DataFlow::TypeTracker::end()).flowsTo(result) } + + /** Gets a reference to a `Mongo` collection use. */ + private DataFlow::LocalSourceNode mongoCollection(DataFlow::TypeTracker t) { t.start() and ( exists(SubscriptNode subscript | result.asCfgNode() = subscript | - subscript.getObject() = mongoClientInstance().getAUse().asCfgNode() + subscript.getObject() = mongoDB().asCfgNode() ) or - result.(DataFlow::AttrRead).getObject() = mongoClientInstance().getAUse() + result.(DataFlow::AttrRead).getObject() = mongoDB() ) or - exists(DataFlow::TypeTracker t2 | result = mongoClientDB(t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = mongoCollection(t2).track(t2, t)) } - /** Gets a reference to a `MongoClient` DB. */ - private DataFlow::Node mongoClientDB() { - mongoClientDB(DataFlow::TypeTracker::end()).flowsTo(result) + /** Gets a reference to a `Mongo` collection use. */ + private DataFlow::Node mongoCollection() { + mongoCollection(DataFlow::TypeTracker::end()).flowsTo(result) } - /** Gets a reference to a `MongoClient` collection. */ - private DataFlow::LocalSourceNode mongoClientCollection(DataFlow::TypeTracker t) { - t.start() and - ( - exists(SubscriptNode subscript | result.asCfgNode() = subscript | - subscript.getObject() = mongoClientDB().asCfgNode() - ) - or - result.(DataFlow::AttrRead).getObject() = mongoClientDB() - ) - or - exists(DataFlow::TypeTracker t2 | result = mongoClientCollection(t2).track(t2, t)) - } - - /** Gets a reference to a `MongoClient` collection. */ - private DataFlow::Node mongoClientCollection() { - mongoClientCollection(DataFlow::TypeTracker::end()).flowsTo(result) - } - - /** This class represents names of find_* relevant MongoClient collection level operation methods. */ - private class MongoClientMethodNames extends string { - MongoClientMethodNames() { - // the find_one_or_404 method is only found in the Pymongo Flask library. + /** This class represents names of find_* relevant `Mongo` collection-level operation methods. */ + private class MongoCollectionMethodNames extends string { + MongoCollectionMethodNames() { this in [ "find", "find_raw_batches", "find_one", "find_one_and_delete", "find_and_modify", "find_one_and_replace", "find_one_and_update", "find_one_or_404" @@ -76,18 +88,15 @@ private module NoSQL { } } - /** Gets a reference to a `MongoClient` Collection method. */ - private DataFlow::Node mongoClientMethod() { - result.(DataFlow::AttrRead).getAttributeName() instanceof MongoClientMethodNames and - ( - result.(DataFlow::AttrRead).getObject() = mongoClientCollection() or - result.(DataFlow::AttrRead) = mongoClientCollection() - ) + /** Gets a reference to a `Mongo` collection method. */ + private DataFlow::Node mongoCollectionMethod() { + mongoCollection() in [result.(DataFlow::AttrRead), result.(DataFlow::AttrRead).getObject()] and + result.(DataFlow::AttrRead).getAttributeName() instanceof MongoCollectionMethodNames } - /** Gets a reference to a `MongoClient` call */ - private class MongoClientCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - MongoClientCall() { this.getFunction() = mongoClientMethod() } + /** Gets a reference to a `Mongo` collection method call */ + private class MongoCollectionCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { + MongoCollectionCall() { this.getFunction() = mongoCollectionMethod() } override DataFlow::Node getQuery() { result = this.getArg(0) } } @@ -95,7 +104,7 @@ private module NoSQL { private class MongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { MongoEngineObjectsCall() { this = - API::moduleImport("mongoengine") + [mongoEngine(), flask_MongoEngine()] .getMember(["Document", "EmbeddedDocument"]) .getASubclass() .getMember("objects") @@ -105,61 +114,6 @@ private module NoSQL { override DataFlow::Node getQuery() { result = this.getArgByName(_) } } - private class FlaskMongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { - FlaskMongoEngineObjectsCall() { - this = - API::moduleImport("flask_mongoengine") - .getMember("MongoEngine") - .getReturn() - .getMember(["Document", "EmbeddedDocument"]) - .getASubclass() - .getMember("objects") - .getACall() - } - - override DataFlow::Node getQuery() { result = this.getArgByName(_) } - } - - private DataFlow::Node flaskMongoEngineInstance() { - result = API::moduleImport("flask_mongoengine").getMember("MongoEngine").getReturn().getAUse() - } - - /** - * A MongoEngine.Document or MongoEngine.EmbeddedDocument subclass which represents a MongoDB document. - */ - private class FlaskMongoEngineDocumentClass extends ClassValue { - FlaskMongoEngineDocumentClass() { - this.getASuperType().getName() in ["Document", "EmbeddedDocument"] and - exists(AttrNode documentClass | - documentClass.getName() in ["Document", "EmbeddedDocument"] and - documentClass.getObject() = flaskMongoEngineInstance().asCfgNode() and - // This is super hacky. It checks to see if the class is a subclass of a flaskMongoEngineInstance.Document - this.getASuperType() - .getAReference() - .getNode() - .(ClassExpr) - .contains(documentClass.getNode().getObject()) - ) - } - } - - private class FlaskMongoEngineDocumentSubclassInstanceCall extends DataFlow::CallCfgNode, - NoSQLQuery::Range { - FlaskMongoEngineDocumentSubclassInstanceCall() { - exists( - DataFlow::CallCfgNode objectsCall, - FlaskMongoEngineDocumentClass flaskMongoEngineDocumentClass - | - objectsCall.getFunction().asExpr().(Attribute).getObject().getAFlowNode() = - flaskMongoEngineDocumentClass.getAReference() and - objectsCall.asCfgNode().(CallNode).getNode().getFunc().(Attribute).getName() = "objects" and - this = objectsCall - ) - } - - override DataFlow::Node getQuery() { result = this.getArgByName(_) } - } - private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { MongoSanitizerCall() { this = From 8527ccc6d6f4aea5aa889b2e69847203c9b2d09d Mon Sep 17 00:00:00 2001 From: jorgectf Date: Wed, 16 Jun 2021 23:19:14 +0200 Subject: [PATCH 086/429] Update .expected --- .../Security/CWE-943/NoSQLInjection.expected | 163 ++++++++---------- 1 file changed, 73 insertions(+), 90 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index dd247bc9206..da28a2d0d15 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,57 +1,53 @@ edges -| flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | -| flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | -| flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | -| flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:20:26:20:32 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:30:21:47 | ControlFlowNode for unsanitized_search | -| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | -| flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | -| flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | -| flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | -| flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | +| flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | +| flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | | mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | +| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | | mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | | mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | +| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | | mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | | mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_flask_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | +| mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | @@ -66,40 +62,37 @@ edges | mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | -| mongoengine_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | -| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | +| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | | pymongo_good.py:12:21:12:27 | ControlFlowNode for request | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | nodes -| flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_bad.py:19:26:19:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_bad.py:19:26:19:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_bad.py:19:26:19:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:19:26:19:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:20:30:20:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:20:26:20:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_good.py:20:26:20:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:20:26:20:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:21:30:21:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_pymongo_bad.py:11:26:11:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_pymongo_bad.py:11:26:11:47 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_pymongo_bad.py:12:30:12:47 | ControlFlowNode for unsanitized_search | semmle.label | ControlFlowNode for unsanitized_search | -| flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_get_db_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -108,21 +101,16 @@ nodes | mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -131,20 +119,20 @@ nodes | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_flask_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_flask_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_document_subclass_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -163,28 +151,23 @@ nodes | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoengine_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | #select -| flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:36:22:46 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:19:26:19:32 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:23:41:23:61 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:19:26:19:32 | ControlFlowNode for request | user-provided value | -| flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:33:14:53 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:26:11:32 | ControlFlowNode for request | user-provided value | -| mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:21:37:21:57 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:20:34:20:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:21:31:21:51 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:22:31:22:51 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_flask_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | This | mongoengine_flask_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | This | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | +| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | +| mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | This | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:44:14:64 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | +| pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From b8e619a60c1cb0d801797a40ebdc2b15a27667a0 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 17 Jun 2021 15:42:45 +0200 Subject: [PATCH 087/429] Extend qhelp references --- .../ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index 339fc5d9d14..9771f8fd0d9 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -30,6 +30,10 @@ +
  • Mongoengine: Documentation.
  • +
  • Flask-Mongoengine: Documentation.
  • +
  • PyMongo: Documentation.
  • +
  • Flask-PyMongo: Documentation.
  • OWASP: NoSQL Injection.
  • Security Stack Exchange Discussion: Question 83231.
  • From 8e3d5ff3f9375f9f3a16cc039f85965e6279bae0 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 17 Jun 2021 15:43:01 +0200 Subject: [PATCH 088/429] Rename mongoclient tests --- ...{mongoclient_subscript_bad.py => mongoengine_subscript_bad.py} | 0 ...ongoclient_subscript_good.py => mongoengine_subscript_good.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoclient_subscript_bad.py => mongoengine_subscript_bad.py} (100%) rename python/ql/test/experimental/query-tests/Security/CWE-943/{mongoclient_subscript_good.py => mongoengine_subscript_good.py} (100%) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py similarity index 100% rename from python/ql/test/experimental/query-tests/Security/CWE-943/mongoclient_subscript_good.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py From 7e6032f5b4dd9c4b5d0a2a29aa892e74c58274e9 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 17 Jun 2021 15:43:54 +0200 Subject: [PATCH 089/429] Port to Decoding --- .../semmle/python/frameworks/Stdlib.qll | 45 ++++++++++++++++++ .../security/injection/NoSQLInjection.qll | 47 +++++++------------ 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 4f3457e0a99..7db995220d4 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/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 experimental.semmle.python.Concepts +private import semmle.python.Concepts private import semmle.python.ApiGraphs /** @@ -98,3 +99,47 @@ private module Re { override DataFlow::Node getRegexNode() { result = regexNode } } } + +// --------------------------------------------------------------------------- +// xmltodict +// --------------------------------------------------------------------------- +/** Gets a reference to the `xmltodict` module. */ +API::Node xmltodict() { result = API::moduleImport("xmltodict") } + +/** + * A call to `xmltodict.parse` + * See https://github.com/martinblech/xmltodict/blob/ae19c452ca000bf243bfc16274c060bf3bf7cf51/xmltodict.py#L198 + */ +private class XmlToDictParseCall extends Decoding::Range, DataFlow::CallCfgNode { + XmlToDictParseCall() { this = xmltodict().getMember("parse").getACall() } + + override predicate mayExecuteInput() { none() } + + override DataFlow::Node getAnInput() { result = this.getArg(0) } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "JSON" } +} + +// --------------------------------------------------------------------------- +// ujson +// --------------------------------------------------------------------------- +/** Gets a reference to the `ujson` module. */ +API::Node ujson() { result = API::moduleImport("ujson") } + +/** + * A call to `ujson.loads` + * See https://pypi.org/project/ujson/#usage + */ +private class UltraJsonLoadsCall extends Decoding::Range, DataFlow::CallCfgNode { + UltraJsonLoadsCall() { this = ujson().getMember("loads").getACall() } + + override predicate mayExecuteInput() { none() } + + override DataFlow::Node getAnInput() { result = this.getArg(0) } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "JSON" } +} diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index 8217f370af7..b15a844605c 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -3,53 +3,37 @@ 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 experimental.semmle.python.Concepts import semmle.python.dataflow.new.RemoteFlowSources -import semmle.python.ApiGraphs import semmle.python.security.dataflow.ChainedConfigs12 +import experimental.semmle.python.Concepts +import semmle.python.Concepts -class JsonLoadsCall extends DataFlow::CallCfgNode { - JsonLoadsCall() { this = API::moduleImport("json").getMember("loads").getACall() } - - DataFlow::Node getLoadNode() { result = this.getArg(0) } -} - -class XmlToDictParseCall extends DataFlow::CallCfgNode { - XmlToDictParseCall() { this = API::moduleImport("xmltodict").getMember("parse").getACall() } - - DataFlow::Node getParseNode() { result = this.getArg(0) } -} - -class UltraJsonLoadsCall extends DataFlow::CallCfgNode { - UltraJsonLoadsCall() { this = API::moduleImport("ujson").getMember("loads").getACall() } - - DataFlow::Node getLoadNode() { result = this.getArg(0) } -} - -class DataToDictSink extends DataFlow::Node { - DataToDictSink() { - this = any(JsonLoadsCall jsonLoads).getLoadNode() or - this = any(XmlToDictParseCall jsonLoads).getParseNode() or - this = any(UltraJsonLoadsCall jsonLoads).getLoadNode() - } -} - +/** + * A taint-tracking configuration for detecting string-to-dict conversions. + */ class RFSToDictConfig extends TaintTracking::Configuration { RFSToDictConfig() { this = "RFSToDictConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSink(DataFlow::Node sink) { sink instanceof DataToDictSink } + override predicate isSink(DataFlow::Node sink) { + exists(Decoding decoding | decoding.getFormat() = "JSON" and sink = decoding) + } override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer = any(NoSQLSanitizer noSQLSanitizer).getAnInput() } } +/** + * A taint-tracking configuration for detecting NoSQL injections (previously converted to a dict). + */ class FromDataDictToSink extends TaintTracking2::Configuration { FromDataDictToSink() { this = "FromDataDictToSink" } - override predicate isSource(DataFlow::Node source) { source instanceof DataToDictSink } + override predicate isSource(DataFlow::Node source) { + exists(Decoding decoding | decoding.getFormat() = "JSON" and source = decoding) + } override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQuery() } @@ -58,6 +42,9 @@ class FromDataDictToSink extends TaintTracking2::Configuration { } } +/** + * A predicate checking string-to-dict conversion and its arrival to a NoSQL injection sink. + */ predicate noSQLInjectionFlow(CustomPathNode source, CustomPathNode sink) { exists( RFSToDictConfig config, DataFlow::PathNode mid1, DataFlow2::PathNode mid2, From 4e74003cd5d70832477141e5696f16c1c30ae977 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 17 Jun 2021 15:44:51 +0200 Subject: [PATCH 090/429] Polish Concepts documentation --- .../experimental/semmle/python/Concepts.qll | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/python/ql/src/experimental/semmle/python/Concepts.qll b/python/ql/src/experimental/semmle/python/Concepts.qll index 2134b32e60a..891a6820801 100644 --- a/python/ql/src/experimental/semmle/python/Concepts.qll +++ b/python/ql/src/experimental/semmle/python/Concepts.qll @@ -147,30 +147,60 @@ class LDAPEscape extends DataFlow::Node { DataFlow::Node getAnInput() { result = range.getAnInput() } } +/** Provides a class for modeling NoSQL execution APIs. */ module NoSQLQuery { + /** + * A data-flow node that executes NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLQuery` instead. + */ abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the NoSQL query to be executed. */ abstract DataFlow::Node getQuery(); } } +/** + * A data-flow node that executes NoSQL queries. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `NoSQLQuery::Range` instead. + */ class NoSQLQuery extends DataFlow::Node { NoSQLQuery::Range range; NoSQLQuery() { this = range } + /** Gets the argument that specifies the NoSQL query to be executed. */ DataFlow::Node getQuery() { result = range.getQuery() } } +/** Provides classes for modeling NoSQL sanitization-related APIs. */ module NoSQLSanitizer { + /** + * A data-flow node that collects functions sanitizing NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLSanitizer` instead. + */ abstract class Range extends DataFlow::Node { + /** Gets the argument that specifies the NoSQL query to be sanitized. */ abstract DataFlow::Node getAnInput(); } } +/** + * A data-flow node that collects functions sanitizing NoSQL queries. + * + * Extend this class to model new APIs. If you want to refine existing API models, + * extend `NoSQLSanitizer::Range` instead. + */ class NoSQLSanitizer extends DataFlow::Node { NoSQLSanitizer::Range range; NoSQLSanitizer() { this = range } + /** Gets the argument that specifies the NoSQL query to be sanitized. */ DataFlow::Node getAnInput() { result = range.getAnInput() } } From eb16018446340ff1b8d6fae7e72af345f93d31dc Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 17 Jun 2021 15:45:05 +0200 Subject: [PATCH 091/429] Update .expected --- .../Security/CWE-943/NoSQLInjection.expected | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index da28a2d0d15..ad4a19510f1 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,173 +1,173 @@ edges | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | +| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | | flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | | flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_good.py:20:19:20:43 | ControlFlowNode for Attribute() | | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | | flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | -| flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | +| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | | flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | | flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:19:21:43 | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | -| flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | -| flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | +| flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | +| flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | -| flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | -| mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | +| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | +| mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | | mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:19:19:19:43 | ControlFlowNode for Attribute() | | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | +| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | +| mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | | mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | +| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | +| mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | | mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_good.py:19:19:19:43 | ControlFlowNode for Attribute() | | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | +| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | +| mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | | mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:19:19:19:43 | ControlFlowNode for Attribute() | | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | -| mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | +| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | +| mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | | mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | +| mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | +| mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | +| mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | +| mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | +| mongoengine_subscript_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_subscript_good.py:19:19:19:43 | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | -| pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | -| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | +| pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | +| pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | | pymongo_good.py:12:21:12:27 | ControlFlowNode for request | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | -| pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | +| pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | nodes | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | | flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_db_document_subclass_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:21:30:21:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_mongoengine_get_db_good.py:21:19:21:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoclient_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoclient_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoclient_subscript_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | -| mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoclient_subscript_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoclient_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoclient_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoclient_subscript_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| flask_pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_connect_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_document_subclass_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | | mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_document_subclass_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_document_subclass_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:18:30:18:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:20:30:20:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| mongoengine_get_db_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_subscript_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_subscript_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | pymongo_good.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| pymongo_good.py:13:30:13:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | +| pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | #select | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | This | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | -| mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoclient_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | This | mongoclient_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | This | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | This | mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From c476c89de5373913ccba1c693ccd3a04166b547c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 16:08:57 +0200 Subject: [PATCH 092/429] Python: Add tests for `peewee` --- .../frameworks/peewee/ConceptsTest.expected | 0 .../frameworks/peewee/ConceptsTest.ql | 2 ++ .../peewee/InlineTaintTest.expected | 3 +++ .../frameworks/peewee/InlineTaintTest.ql | 1 + .../frameworks/peewee/sql_execution.py | 19 +++++++++++++++++++ 5 files changed, 25 insertions(+) create mode 100644 python/ql/test/library-tests/frameworks/peewee/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/peewee/ConceptsTest.ql create mode 100644 python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.expected create mode 100644 python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.ql create mode 100644 python/ql/test/library-tests/frameworks/peewee/sql_execution.py diff --git a/python/ql/test/library-tests/frameworks/peewee/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/peewee/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/library-tests/frameworks/peewee/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/peewee/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/peewee/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.expected b/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.expected new file mode 100644 index 00000000000..79d760d87f4 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.expected @@ -0,0 +1,3 @@ +argumentToEnsureNotTaintedNotMarkedAsSpurious +untaintedArgumentToEnsureTaintedNotMarkedAsMissing +failures diff --git a/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.ql b/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.ql new file mode 100644 index 00000000000..027ad8667be --- /dev/null +++ b/python/ql/test/library-tests/frameworks/peewee/InlineTaintTest.ql @@ -0,0 +1 @@ +import experimental.meta.InlineTaintTest diff --git a/python/ql/test/library-tests/frameworks/peewee/sql_execution.py b/python/ql/test/library-tests/frameworks/peewee/sql_execution.py new file mode 100644 index 00000000000..c9146cad2eb --- /dev/null +++ b/python/ql/test/library-tests/frameworks/peewee/sql_execution.py @@ -0,0 +1,19 @@ +import peewee +import playhouse.pool + +# This is just one example of one of the support databases +# see https://docs.peewee-orm.com/en/latest/peewee/database.html +db = peewee.MySQLDatabase() + +conn = db.connection() +cursor = conn.cursor() +cursor.execute("sql") # $ MISSING: getSql="sql" + +cursor = db.cursor() +cursor.execute("sql") # $ MISSING: getSql="sql" + +db.execute_sql("sql") # $ MISSING: getSql="sql" + +# Pool extension +pool = playhouse.pool.PooledMySQLDatabase(...) +pool.execute_sql("sql") # $ MISSING: getSql="sql" From 5cfc43395ba99471bc17371996470fa13ded4ddc Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 17:15:12 +0200 Subject: [PATCH 093/429] Python: Refactor PEP249 to encapsulate in module So global namespace doesn't contain `Connection` whenever `PEP249.qll` is imported --- .../ql/src/semmle/python/frameworks/Aioch.qll | 1 - .../python/frameworks/ClickhouseDriver.qll | 2 +- .../src/semmle/python/frameworks/Django.qll | 4 +- .../src/semmle/python/frameworks/MySQLdb.qll | 2 +- .../ql/src/semmle/python/frameworks/Mysql.qll | 2 +- .../src/semmle/python/frameworks/PEP249.qll | 107 ++------------ .../src/semmle/python/frameworks/Psycopg2.qll | 2 +- .../src/semmle/python/frameworks/PyMySQL.qll | 2 +- .../src/semmle/python/frameworks/Stdlib.qll | 2 +- .../python/frameworks/internal/PEP249Impl.qll | 134 ++++++++++++++++++ 10 files changed, 154 insertions(+), 104 deletions(-) create mode 100644 python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll diff --git a/python/ql/src/semmle/python/frameworks/Aioch.qll b/python/ql/src/semmle/python/frameworks/Aioch.qll index ede732e35dc..8595a708fb7 100644 --- a/python/ql/src/semmle/python/frameworks/Aioch.qll +++ b/python/ql/src/semmle/python/frameworks/Aioch.qll @@ -8,7 +8,6 @@ private import python private import semmle.python.Concepts private import semmle.python.ApiGraphs -private import semmle.python.frameworks.PEP249 private import semmle.python.frameworks.ClickhouseDriver /** diff --git a/python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll b/python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll index 8863b1dbe66..949f4d5e870 100644 --- a/python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll +++ b/python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll @@ -23,7 +23,7 @@ module ClickhouseDriver { * `clickhouse_driver` implements PEP249, * providing ways to execute SQL statements against a database. */ - class ClickHouseDriverPEP249 extends PEP249ModuleApiNode { + class ClickHouseDriverPEP249 extends PEP249::PEP249ModuleApiNode { ClickHouseDriverPEP249() { this = API::moduleImport("clickhouse_driver") } } diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/src/semmle/python/frameworks/Django.qll index d9f59b05fa6..d3ff9248e80 100644 --- a/python/ql/src/semmle/python/frameworks/Django.qll +++ b/python/ql/src/semmle/python/frameworks/Django.qll @@ -313,7 +313,7 @@ private module PrivateDjango { /** * `django.db` implements PEP249, providing ways to execute SQL statements against a database. */ - private class DjangoDb extends PEP249ModuleApiNode { + private class DjangoDb extends PEP249::PEP249ModuleApiNode { DjangoDb() { this = API::moduleImport("django").getMember("db") } } @@ -322,7 +322,7 @@ private module PrivateDjango { /** Gets a reference to the `django.db.connection` object. */ API::Node connection() { result = db().getMember("connection") } - class DjangoDbConnection extends Connection::InstanceSource { + class DjangoDbConnection extends PEP249::Connection::InstanceSource { DjangoDbConnection() { this = connection().getAUse() } } diff --git a/python/ql/src/semmle/python/frameworks/MySQLdb.qll b/python/ql/src/semmle/python/frameworks/MySQLdb.qll index 5f10cdc0c84..e1d7262c087 100644 --- a/python/ql/src/semmle/python/frameworks/MySQLdb.qll +++ b/python/ql/src/semmle/python/frameworks/MySQLdb.qll @@ -25,7 +25,7 @@ private module MySQLdb { // MySQLdb // --------------------------------------------------------------------------- /** MySQLdb implements PEP 249, providing ways to execute SQL statements against a database. */ - class MySQLdb extends PEP249ModuleApiNode { + class MySQLdb extends PEP249::PEP249ModuleApiNode { MySQLdb() { this = API::moduleImport("MySQLdb") } } } diff --git a/python/ql/src/semmle/python/frameworks/Mysql.qll b/python/ql/src/semmle/python/frameworks/Mysql.qll index 5049124ad83..a1a297e88c0 100644 --- a/python/ql/src/semmle/python/frameworks/Mysql.qll +++ b/python/ql/src/semmle/python/frameworks/Mysql.qll @@ -30,7 +30,7 @@ private module Mysql { * The mysql.connector module * See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html */ - class MysqlConnector extends PEP249ModuleApiNode { + class MysqlConnector extends PEP249::PEP249ModuleApiNode { MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") } } } diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/src/semmle/python/frameworks/PEP249.qll index ef58ef1fbdb..6f9b4f2ed4e 100644 --- a/python/ql/src/semmle/python/frameworks/PEP249.qll +++ b/python/ql/src/semmle/python/frameworks/PEP249.qll @@ -8,119 +8,36 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.RemoteFlowSources private import semmle.python.Concepts private import semmle.python.ApiGraphs +import semmle.python.frameworks.internal.PEP249Impl /** * A module implementing PEP 249. Extend this class for implementations. * - * DEPRECATED: Extend `PEP249ModuleApiNode` instead. + * DEPRECATED: Extend `PEP249::PEP249ModuleApiNode` instead. */ abstract deprecated class PEP249Module extends DataFlow::Node { } /** - * An abstract class encompassing API graph nodes that implement PEP 249. - * Extend this class for implementations. + * DEPRECATED: Use `PEP249::PEP249ModuleApiNode` instead. */ -abstract class PEP249ModuleApiNode extends API::Node { - /** Gets a string representation of this element. */ - override string toString() { result = this.(API::Node).toString() } -} - -/** Gets a reference to a connect call. */ -DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() } +deprecated class PEP249ModuleApiNode = PEP249::PEP249ModuleApiNode; /** - * Provides models for the `db.Connection` class - * - * See https://www.python.org/dev/peps/pep-0249/#connection-objects. + * DEPRECATED: Use `PEP249::Connection` instead. */ -module Connection { - /** - * A source of instances of `db.Connection`, 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 external - * libraries. - * - * 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`. - */ - abstract class InstanceSource extends DataFlow::Node { } - - /** A direct instantiation of `db.Connection`. */ - private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode { - ClassInstantiation() { this.getFunction() = connect() } - } - - /** Gets a reference to an instance of `db.Connection`. */ - private DataFlow::LocalSourceNode 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 `db.Connection`. */ - DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } -} +deprecated module Connection = PEP249::Connection; /** - * Provides models for the `cursor` method on a connection. - * See https://www.python.org/dev/peps/pep-0249/#cursor. + * DEPRECATED: Use `PEP249::cursor` instead. */ -module cursor { - /** Gets a reference to the `cursor` method on a connection. */ - private DataFlow::LocalSourceNode methodRef(DataFlow::TypeTracker t) { - t.startInAttr("cursor") and - result = Connection::instance() - or - exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t)) - } - - /** Gets a reference to the `cursor` method on a connection. */ - DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) } - - /** Gets a reference to a result of calling the `cursor` method on a connection. */ - private DataFlow::LocalSourceNode methodResult(DataFlow::TypeTracker t) { - t.start() and - result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode() - or - exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t)) - } - - /** Gets a reference to a result of calling the `cursor` method on a connection. */ - DataFlow::Node methodResult() { methodResult(DataFlow::TypeTracker::end()).flowsTo(result) } -} +deprecated module cursor = PEP249::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. + * DEPRECATED: Use `PEP249::execute` instead. */ -private DataFlow::LocalSourceNode execute(DataFlow::TypeTracker t) { - t.startInAttr("execute") and - result in [cursor::methodResult(), Connection::instance()] - or - exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t)) -} +deprecated predicate execute = PEP249::execute/0; /** - * 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. + * DEPRECATED: Use `PEP249::connect` instead. */ -DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) } - -/** A call to the `execute` method on a cursor (or on a connection). */ -private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode { - ExecuteCall() { this.getFunction() = execute() } - - override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } -} +deprecated predicate connect = PEP249::connect/0; diff --git a/python/ql/src/semmle/python/frameworks/Psycopg2.qll b/python/ql/src/semmle/python/frameworks/Psycopg2.qll index d966776b082..01f33b37cd0 100644 --- a/python/ql/src/semmle/python/frameworks/Psycopg2.qll +++ b/python/ql/src/semmle/python/frameworks/Psycopg2.qll @@ -23,7 +23,7 @@ private module Psycopg2 { // Psycopg // --------------------------------------------------------------------------- /** psycopg2 implements PEP 249, providing ways to execute SQL statements against a database. */ - class Psycopg2 extends PEP249ModuleApiNode { + class Psycopg2 extends PEP249::PEP249ModuleApiNode { Psycopg2() { this = API::moduleImport("psycopg2") } } } diff --git a/python/ql/src/semmle/python/frameworks/PyMySQL.qll b/python/ql/src/semmle/python/frameworks/PyMySQL.qll index 452b87ed030..834dd2438dc 100644 --- a/python/ql/src/semmle/python/frameworks/PyMySQL.qll +++ b/python/ql/src/semmle/python/frameworks/PyMySQL.qll @@ -16,7 +16,7 @@ private import semmle.python.frameworks.PEP249 */ private module PyMySQL { /** PyMySQL implements PEP 249, providing ways to execute SQL statements against a database. */ - class PyMySQLPEP249 extends PEP249ModuleApiNode { + class PyMySQLPEP249 extends PEP249::PEP249ModuleApiNode { PyMySQLPEP249() { this = API::moduleImport("pymysql") } } } diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/src/semmle/python/frameworks/Stdlib.qll index 66018e45b62..1f5afdc463b 100644 --- a/python/ql/src/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/semmle/python/frameworks/Stdlib.qll @@ -885,7 +885,7 @@ private module Stdlib { * * See https://devdocs.io/python~3.9/library/sqlite3 */ - class Sqlite3 extends PEP249ModuleApiNode { + class Sqlite3 extends PEP249::PEP249ModuleApiNode { Sqlite3() { this = API::moduleImport("sqlite3") } } diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll new file mode 100644 index 00000000000..bcef36a17b5 --- /dev/null +++ b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll @@ -0,0 +1,134 @@ +/** + * INTERNAL: Do not use. + * + * Provides internal implementation of PEP249. This currently resides in a different + * file than `python/ql/src/semmle/python/frameworks/PEP249.qll`, since we used to + * export everything without being encapsulated in a module, and shadowing rules means + * that we can't just add the module directly to that file :( + * + * So once we can remove those deprecated things (Start of July 2022), we can also move + * the core implementation into its' proper place. + * + * Provides classes modeling PEP 249. + * See https://www.python.org/dev/peps/pep-0249/. + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides classes modeling PEP 249. + */ +module PEP249 { + /** + * An abstract class encompassing API graph nodes that implement PEP 249. + * Extend this class for implementations. + */ + abstract class PEP249ModuleApiNode extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + /** Gets a reference to a connect call. */ + DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() } + + /** + * Provides models for the `db.Connection` class + * + * See https://www.python.org/dev/peps/pep-0249/#connection-objects. + */ + module Connection { + /** + * A source of instances of `db.Connection`, 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 external + * libraries. + * + * 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`. + */ + abstract class InstanceSource extends DataFlow::Node { } + + /** A direct instantiation of `db.Connection`. */ + private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode { + ClassInstantiation() { this.getFunction() = connect() } + } + + /** Gets a reference to an instance of `db.Connection`. */ + private DataFlow::LocalSourceNode 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 `db.Connection`. */ + DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } + } + + /** + * 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 `cursor` method on a connection. */ + private DataFlow::LocalSourceNode methodRef(DataFlow::TypeTracker t) { + t.startInAttr("cursor") and + result = Connection::instance() + or + exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t)) + } + + /** Gets a reference to the `cursor` method on a connection. */ + DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) } + + /** Gets a reference to a result of calling the `cursor` method on a connection. */ + private DataFlow::LocalSourceNode methodResult(DataFlow::TypeTracker t) { + t.start() and + result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode() + or + exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t)) + } + + /** Gets a reference to a result of calling the `cursor` method on a connection. */ + DataFlow::Node methodResult() { methodResult(DataFlow::TypeTracker::end()).flowsTo(result) } + } + + /** + * 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::LocalSourceNode execute(DataFlow::TypeTracker t) { + t.startInAttr("execute") and + 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 (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() { execute(DataFlow::TypeTracker::end()).flowsTo(result) } + + /** A call to the `execute` method on a cursor (or on a connection). */ + private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode { + ExecuteCall() { this.getFunction() = execute() } + + override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } + } +} From 6be0db2c227de9248befd8a5498bf5ccd385fad3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 17:24:28 +0200 Subject: [PATCH 094/429] Python: Improve QLDoc of PEP249 modeling --- .../python/frameworks/internal/PEP249Impl.qll | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll index bcef36a17b5..80f4c4b990c 100644 --- a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll @@ -20,47 +20,47 @@ private import semmle.python.Concepts private import semmle.python.ApiGraphs /** - * Provides classes modeling PEP 249. + * Provides classes modeling database interfaces following PEP 249. + * See https://www.python.org/dev/peps/pep-0249/. */ module PEP249 { /** - * An abstract class encompassing API graph nodes that implement PEP 249. - * Extend this class for implementations. + * An API graph node representing a module that implements PEP 249. */ abstract class PEP249ModuleApiNode extends API::Node { /** Gets a string representation of this element. */ override string toString() { result = this.(API::Node).toString() } } - /** Gets a reference to a connect call. */ + /** Gets a reference to the `connect` function of a module that implements PEP 249. */ DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAUse() } /** - * Provides models for the `db.Connection` class + * Provides models for database connections (following PEP 249). * * See https://www.python.org/dev/peps/pep-0249/#connection-objects. */ module Connection { /** - * A source of instances of `db.Connection`, extend this class to model new instances. + * A source of database connections (following PEP 249), 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 external * libraries. * - * Use the predicate `Connection::instance()` to get references to instances of `db.Connection`. + * Use the predicate `Connection::instance()` to get references database connections (following PEP 249). * * Extend this class if the module implementing PEP 249 offers more direct ways to obtain * a connection than going through `connect`. */ abstract class InstanceSource extends DataFlow::Node { } - /** A direct instantiation of `db.Connection`. */ - private class ClassInstantiation extends InstanceSource, DataFlow::CallCfgNode { - ClassInstantiation() { this.getFunction() = connect() } + /** A call to the `connect` function of a module that implements PEP 249. */ + private class ConnectCall extends InstanceSource, DataFlow::CallCfgNode { + ConnectCall() { this.getFunction() = connect() } } - /** Gets a reference to an instance of `db.Connection`. */ + /** Gets a reference to a database connection (following PEP 249). */ private DataFlow::LocalSourceNode instance(DataFlow::TypeTracker t) { t.start() and result instanceof InstanceSource @@ -68,16 +68,18 @@ module PEP249 { exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t)) } - /** Gets a reference to an instance of `db.Connection`. */ + /** Gets a reference to a database connection (following PEP 249). */ DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } } /** - * Provides models for the `cursor` method on a connection. + * Provides models for database cursors (following PEP 249). + * + * These are are returned by the `cursor` method on a database connection. * See https://www.python.org/dev/peps/pep-0249/#cursor. */ module cursor { - /** Gets a reference to the `cursor` method on a connection. */ + /** Gets a reference to the `cursor` method on a database connection. */ private DataFlow::LocalSourceNode methodRef(DataFlow::TypeTracker t) { t.startInAttr("cursor") and result = Connection::instance() @@ -85,10 +87,10 @@ module PEP249 { exists(DataFlow::TypeTracker t2 | result = methodRef(t2).track(t2, t)) } - /** Gets a reference to the `cursor` method on a connection. */ + /** Gets a reference to the `cursor` method on a database connection. */ DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) } - /** Gets a reference to a result of calling the `cursor` method on a connection. */ + /** Gets a reference to a result of calling the `cursor` method on a database connection. */ private DataFlow::LocalSourceNode methodResult(DataFlow::TypeTracker t) { t.start() and result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode() @@ -96,7 +98,7 @@ module PEP249 { exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t)) } - /** Gets a reference to a result of calling the `cursor` method on a connection. */ + /** Gets a reference to a result of calling the `cursor` method on a database connection. */ DataFlow::Node methodResult() { methodResult(DataFlow::TypeTracker::end()).flowsTo(result) } } From d8db83d0818388c3f3dee1b5f75874297b87bfed Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 17:29:32 +0200 Subject: [PATCH 095/429] Python: Add cursor::instance for PEP249 For Peewee modeling I want to be able to define new cursor instances just like I can do for connections. --- .../python/frameworks/internal/PEP249Impl.qll | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll index 80f4c4b990c..b6e36f3a78b 100644 --- a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll @@ -79,6 +79,31 @@ module PEP249 { * See https://www.python.org/dev/peps/pep-0249/#cursor. */ module cursor { + /** + * A source of database cursors (following PEP 249), 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 external + * libraries. + * + * Use the predicate `Connection::instance()` to get references database cursors (following PEP 249). + * + * Extend this class if the module implementing PEP 249 offers more direct ways to obtain + * a connection than going through `connect`. + */ + abstract class InstanceSource extends DataFlow::LocalSourceNode { } + + /** Gets a reference to a database cursor. */ + private DataFlow::LocalSourceNode 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 a database cursor. */ + DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } + /** Gets a reference to the `cursor` method on a database connection. */ private DataFlow::LocalSourceNode methodRef(DataFlow::TypeTracker t) { t.startInAttr("cursor") and @@ -90,6 +115,11 @@ module PEP249 { /** Gets a reference to the `cursor` method on a database connection. */ DataFlow::Node methodRef() { methodRef(DataFlow::TypeTracker::end()).flowsTo(result) } + /** A call to the `cursor` method on a database connection */ + private class CursorCall extends InstanceSource, DataFlow::CallCfgNode { + CursorCall() { this.getFunction() = methodRef() } + } + /** Gets a reference to a result of calling the `cursor` method on a database connection. */ private DataFlow::LocalSourceNode methodResult(DataFlow::TypeTracker t) { t.start() and @@ -98,8 +128,14 @@ module PEP249 { exists(DataFlow::TypeTracker t2 | result = methodResult(t2).track(t2, t)) } - /** Gets a reference to a result of calling the `cursor` method on a database connection. */ - DataFlow::Node methodResult() { methodResult(DataFlow::TypeTracker::end()).flowsTo(result) } + /** + * DEPRECATED: Use `Cursor::instance()` to get references to database cursors instead. + * + * Gets a reference to a result of calling the `cursor` method on a database connection. + */ + deprecated DataFlow::Node methodResult() { + methodResult(DataFlow::TypeTracker::end()).flowsTo(result) + } } /** @@ -112,7 +148,7 @@ module PEP249 { */ private DataFlow::LocalSourceNode execute(DataFlow::TypeTracker t) { t.startInAttr("execute") and - result in [cursor::methodResult(), Connection::instance()] + result in [cursor::instance(), Connection::instance()] or exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t)) } From 1317ae298ce6f1b614dae86e435f14b95f50b6e2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 17:30:35 +0200 Subject: [PATCH 096/429] Python: Rename `cursor` => `Cursor` in PEP249 Notice that since this will be part of the same PR as 5cfc433, it is OK to do this change without keeping `PEP249::cursor` for backwards compatibility. --- python/ql/src/semmle/python/frameworks/PEP249.qll | 4 ++-- .../ql/src/semmle/python/frameworks/internal/PEP249Impl.qll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/src/semmle/python/frameworks/PEP249.qll index 6f9b4f2ed4e..2ad7bc8898f 100644 --- a/python/ql/src/semmle/python/frameworks/PEP249.qll +++ b/python/ql/src/semmle/python/frameworks/PEP249.qll @@ -28,9 +28,9 @@ deprecated class PEP249ModuleApiNode = PEP249::PEP249ModuleApiNode; deprecated module Connection = PEP249::Connection; /** - * DEPRECATED: Use `PEP249::cursor` instead. + * DEPRECATED: Use `PEP249::Cursor` instead. */ -deprecated module cursor = PEP249::cursor; +deprecated module cursor = PEP249::Cursor; /** * DEPRECATED: Use `PEP249::execute` instead. diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll index b6e36f3a78b..254dcb98cb6 100644 --- a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll @@ -78,7 +78,7 @@ module PEP249 { * These are are returned by the `cursor` method on a database connection. * See https://www.python.org/dev/peps/pep-0249/#cursor. */ - module cursor { + module Cursor { /** * A source of database cursors (following PEP 249), extend this class to model new instances. * @@ -148,7 +148,7 @@ module PEP249 { */ private DataFlow::LocalSourceNode execute(DataFlow::TypeTracker t) { t.startInAttr("execute") and - result in [cursor::instance(), Connection::instance()] + result in [Cursor::instance(), Connection::instance()] or exists(DataFlow::TypeTracker t2 | result = execute(t2).track(t2, t)) } From 97571e0b4fe0c30974d42e9201935cfcc2d7f9a3 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Fri, 25 Jun 2021 17:50:59 +0200 Subject: [PATCH 097/429] Python: Add modeling of `peewee` --- docs/codeql/support/reusables/frameworks.rst | 1 + .../2021-06-25-add-peewee-modeling.md | 2 + python/ql/src/semmle/python/Frameworks.qll | 1 + .../src/semmle/python/frameworks/Peewee.qll | 192 ++++++++++++++++++ .../frameworks/peewee/sql_execution.py | 8 +- 5 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 python/change-notes/2021-06-25-add-peewee-modeling.md create mode 100644 python/ql/src/semmle/python/frameworks/Peewee.qll diff --git a/docs/codeql/support/reusables/frameworks.rst b/docs/codeql/support/reusables/frameworks.rst index dd52ded0ec1..5af414a8153 100644 --- a/docs/codeql/support/reusables/frameworks.rst +++ b/docs/codeql/support/reusables/frameworks.rst @@ -174,6 +174,7 @@ Python built-in support MySQL-python, Database psycopg2, Database sqlite3, Database + peewee, Database ORM cryptography, Cryptography library pycryptodome, Cryptography library pycryptodomex, Cryptography library diff --git a/python/change-notes/2021-06-25-add-peewee-modeling.md b/python/change-notes/2021-06-25-add-peewee-modeling.md new file mode 100644 index 00000000000..ff5b4025d47 --- /dev/null +++ b/python/change-notes/2021-06-25-add-peewee-modeling.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added modeling of raw SQL execution from the PyPI package `peewee`. diff --git a/python/ql/src/semmle/python/Frameworks.qll b/python/ql/src/semmle/python/Frameworks.qll index 48e47108bbe..6e201babd35 100644 --- a/python/ql/src/semmle/python/Frameworks.qll +++ b/python/ql/src/semmle/python/Frameworks.qll @@ -25,6 +25,7 @@ private import semmle.python.frameworks.Rsa private import semmle.python.frameworks.Simplejson private import semmle.python.frameworks.Stdlib private import semmle.python.frameworks.Tornado +private import semmle.python.frameworks.Peewee private import semmle.python.frameworks.Twisted private import semmle.python.frameworks.Ujson private import semmle.python.frameworks.Yaml diff --git a/python/ql/src/semmle/python/frameworks/Peewee.qll b/python/ql/src/semmle/python/frameworks/Peewee.qll new file mode 100644 index 00000000000..189ab14876a --- /dev/null +++ b/python/ql/src/semmle/python/frameworks/Peewee.qll @@ -0,0 +1,192 @@ +/** + * Provides classes modeling security-relevant aspects of the `peewee` PyPI package. + * See + * - https://pypi.org/project/peewee/ + * - https://docs.peewee-orm.com/en/latest/index.html + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 + +/** + * Provides models for the `peewee` PyPI package. + * See + * - https://pypi.org/project/peewee/ + * - https://docs.peewee-orm.com/en/latest/index.html + */ +private module Peewee { + /** Provides models for the `peewee.Database` class and subclasses. */ + module Database { + /** Gets a reference to the `peewee.Database` class or any subclass. */ + API::Node subclassRef() { + result = API::moduleImport("peewee").getMember("Database").getASubclass*() + or + // known subclasses + result = + API::moduleImport("peewee") + .getMember(["SqliteDatabase", "MySQLDatabase", "PostgresqlDatabase"]) + .getASubclass*() + or + // Ohter known subclasses, semi auto generated by using + // ```codeql + // class DBClass extends Class, SelfRefMixin { + // DBClass() { + // exists(this.getLocation().getFile().getRelativePath()) and + // this.getName().matches("%Database") and + // this.getABase().(Name).getId().matches("%Database") + // } + // } + // + // from DBClass dbClass, Module mod + // where + // dbClass.getScope() = mod + // select mod.getName()+ "." + dbClass.getName() + // ``` + result = + API::moduleImport("playhouse") + .getMember("apsw_ext") + .getMember("APSWDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("cockroachdb") + .getMember("CockroachDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("cockroachdb") + .getMember("PooledCockroachDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("mysql_ext") + .getMember("MySQLConnectorDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledCSqliteExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledMySQLDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledPostgresqlDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledPostgresqlExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledSqliteDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("PooledSqliteExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("_PooledPostgresqlDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("pool") + .getMember("_PooledSqliteDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("postgres_ext") + .getMember("PostgresqlExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("sqlcipher_ext") + .getMember("SqlCipherDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("sqlcipher_ext") + .getMember("SqlCipherExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("sqlite_ext") + .getMember("CSqliteExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("sqlite_ext") + .getMember("SqliteExtDatabase") + .getASubclass*() + or + result = + API::moduleImport("playhouse") + .getMember("sqliteq") + .getMember("SqliteQueueDatabase") + .getASubclass*() + } + + /** Gets a reference to an instance of `peewee.Database` or any subclass. */ + API::Node instance() { result = subclassRef().getReturn() } + } + + /** + * A call to the `connection` method on a `peewee.Database` instance. + * https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.connection. + */ + class PeeweeDatabaseConnectionCall extends PEP249::Connection::InstanceSource, + DataFlow::CallCfgNode { + PeeweeDatabaseConnectionCall() { + this = Database::instance().getMember("connection").getACall() + } + } + + /** + * A call to the `cursor` method on a `peewee.Database` instance. + * https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.cursor. + */ + class PeeweeDatabaseCursorCall extends PEP249::Cursor::InstanceSource, DataFlow::CallCfgNode { + PeeweeDatabaseCursorCall() { this = Database::instance().getMember("cursor").getACall() } + } + + /** + * A call to the `execute_sql` method on a `peewee.Database` instance. + * See https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.execute_sql. + */ + class PeeweeDatabaseExecuteSqlCall extends SqlExecution::Range, DataFlow::CallCfgNode { + PeeweeDatabaseExecuteSqlCall() { + this = Database::instance().getMember("execute_sql").getACall() + } + + override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } + } +} diff --git a/python/ql/test/library-tests/frameworks/peewee/sql_execution.py b/python/ql/test/library-tests/frameworks/peewee/sql_execution.py index c9146cad2eb..e6f195eeb47 100644 --- a/python/ql/test/library-tests/frameworks/peewee/sql_execution.py +++ b/python/ql/test/library-tests/frameworks/peewee/sql_execution.py @@ -7,13 +7,13 @@ db = peewee.MySQLDatabase() conn = db.connection() cursor = conn.cursor() -cursor.execute("sql") # $ MISSING: getSql="sql" +cursor.execute("sql") # $ getSql="sql" cursor = db.cursor() -cursor.execute("sql") # $ MISSING: getSql="sql" +cursor.execute("sql") # $ getSql="sql" -db.execute_sql("sql") # $ MISSING: getSql="sql" +db.execute_sql("sql") # $ getSql="sql" # Pool extension pool = playhouse.pool.PooledMySQLDatabase(...) -pool.execute_sql("sql") # $ MISSING: getSql="sql" +pool.execute_sql("sql") # $ getSql="sql" From 59711424bd88abf2caf7fb7459f471ea778baf9e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 28 Jun 2021 11:48:28 +0200 Subject: [PATCH 098/429] Python: Fix qhelp for NoSQL injection --- .../ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp index 9771f8fd0d9..2bfd5682010 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.qhelp @@ -20,14 +20,14 @@ NoSQL injections can be prevented by escaping user-input's special characters that are passed into the NoSQL query from the user-supplied source. Alternatively, using a sanitize library such as MongoSanitizer will ensure that user-supplied sources can not act as a malicious query.

    - +

    In the example below, the user-supplied source is passed to a MongoDB function that queries the MongoDB database.

    This can be fixed by using a sanitizer library like MongoSanitizer as shown in this annotated code version below.

    - +
  • Mongoengine: Documentation.
  • From 318694ccc86bc2251493e06b4b0e1a7dac6e206e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 28 Jun 2021 13:17:45 +0200 Subject: [PATCH 099/429] Python: Don't rely on `d = d.getOutput()` for `Decoding` Although it is for `json.loads` and the like. --- .../semmle/python/security/injection/NoSQLInjection.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll index b15a844605c..fb3890d2f7e 100644 --- a/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll +++ b/python/ql/src/experimental/semmle/python/security/injection/NoSQLInjection.qll @@ -17,7 +17,7 @@ class RFSToDictConfig extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } override predicate isSink(DataFlow::Node sink) { - exists(Decoding decoding | decoding.getFormat() = "JSON" and sink = decoding) + exists(Decoding decoding | decoding.getFormat() = "JSON" and sink = decoding.getOutput()) } override predicate isSanitizer(DataFlow::Node sanitizer) { @@ -32,7 +32,7 @@ class FromDataDictToSink extends TaintTracking2::Configuration { FromDataDictToSink() { this = "FromDataDictToSink" } override predicate isSource(DataFlow::Node source) { - exists(Decoding decoding | decoding.getFormat() = "JSON" and source = decoding) + exists(Decoding decoding | decoding.getFormat() = "JSON" and source = decoding.getOutput()) } override predicate isSink(DataFlow::Node sink) { sink = any(NoSQLQuery noSQLQuery).getQuery() } From 0ca4f240d907a8d1f74fc6f6bf578d23bacebcd8 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 28 Jun 2021 20:13:53 +0200 Subject: [PATCH 100/429] Merge tests and update `.expected` --- .../Security/CWE-943/NoSQLInjection.expected | 272 +++++++++--------- ...get_db_bad.py => flask_mongoengine_bad.py} | 13 +- ...sk_mongoengine_db_document_subclass_bad.py | 24 -- ...k_mongoengine_db_document_subclass_good.py | 26 -- ...t_db_good.py => flask_mongoengine_good.py} | 12 +- .../Security/CWE-943/mongoengine_bad.py | 64 +++++ .../CWE-943/mongoengine_connect_bad.py | 24 -- .../CWE-943/mongoengine_connect_good.py | 26 -- .../mongoengine_connect_via_connection_bad.py | 25 -- ...mongoengine_connect_via_connection_good.py | 27 -- .../mongoengine_document_subclass_bad.py | 23 -- .../mongoengine_document_subclass_good.py | 25 -- .../CWE-943/mongoengine_get_db_bad.py | 24 -- .../CWE-943/mongoengine_get_db_good.py | 26 -- .../mongoengine_get_db_via_connection_bad.py | 25 -- .../mongoengine_get_db_via_connection_good.py | 27 -- .../Security/CWE-943/mongoengine_good.py | 68 +++++ .../CWE-943/mongoengine_subscript_bad.py | 24 -- .../CWE-943/mongoengine_subscript_good.py | 26 -- 19 files changed, 288 insertions(+), 493 deletions(-) rename python/ql/test/experimental/query-tests/Security/CWE-943/{flask_mongoengine_get_db_bad.py => flask_mongoengine_bad.py} (60%) delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py rename python/ql/test/experimental/query-tests/Security/CWE-943/{flask_mongoengine_get_db_good.py => flask_mongoengine_good.py} (68%) create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py create mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py delete mode 100644 python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index ad4a19510f1..10c1f852df5 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,18 +1,18 @@ edges -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | -| flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_db_document_subclass_good.py:20:19:20:43 | ControlFlowNode for Attribute() | -| flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | -| flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_get_db_good.py:21:19:21:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | +| flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | +| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:21:19:21:43 | ControlFlowNode for Attribute() | +| flask_mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -20,48 +20,48 @@ edges | flask_pymongo_good.py:12:21:12:27 | ControlFlowNode for request | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | flask_pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | -| mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | -| mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | -| mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_good.py:19:19:19:43 | ControlFlowNode for Attribute() | -| mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | -| mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | -| mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_connect_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | -| mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | -| mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | -| mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_document_subclass_good.py:19:19:19:43 | ControlFlowNode for Attribute() | -| mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | -| mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | -| mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_good.py:19:19:19:43 | ControlFlowNode for Attribute() | -| mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | -| mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | -| mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_get_db_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | -| mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | -| mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | -| mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | -| mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | -| mongoengine_subscript_good.py:18:21:18:27 | ControlFlowNode for request | mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | -| mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | -| mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_subscript_good.py:19:19:19:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | +| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | +| mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -70,24 +70,24 @@ edges | pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | nodes -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_db_document_subclass_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_db_document_subclass_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_db_document_subclass_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| flask_mongoengine_get_db_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_get_db_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_get_db_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_get_db_good.py:21:19:21:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:21:19:21:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| flask_mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -97,60 +97,60 @@ nodes | flask_pymongo_good.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_connect_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_connect_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_connect_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_connect_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_connect_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_document_subclass_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_document_subclass_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_document_subclass_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_document_subclass_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_document_subclass_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_document_subclass_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_document_subclass_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_get_db_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_via_connection_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_get_db_via_connection_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_get_db_via_connection_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_get_db_via_connection_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_get_db_via_connection_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_subscript_bad.py:17:21:17:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_subscript_bad.py:17:21:17:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_subscript_bad.py:18:19:18:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_subscript_good.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_subscript_good.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_subscript_good.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_subscript_good.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:19:19:19:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:26:21:26:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -161,13 +161,13 @@ nodes | pymongo_good.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | pymongo_good.py:13:19:13:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | #select -| flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_db_document_subclass_bad.py:21:34:21:44 | ControlFlowNode for json_search | This | flask_mongoengine_db_document_subclass_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_get_db_bad.py:23:39:23:59 | ControlFlowNode for Dict | This | flask_mongoengine_get_db_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_connect_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_connect_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_connect_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_document_subclass_bad.py:20:34:20:44 | ControlFlowNode for json_search | This | mongoengine_document_subclass_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_bad.py:21:26:21:46 | ControlFlowNode for Dict | This | mongoengine_get_db_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | -| mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_get_db_via_connection_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_get_db_via_connection_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_subscript_bad.py:21:29:21:49 | ControlFlowNode for Dict | This | mongoengine_subscript_bad.py:17:21:17:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py similarity index 60% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py index 468e1d865a7..9fc8aaefc0f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_bad.py @@ -14,13 +14,20 @@ class Movie(db.Document): Movie(title='test').save() -@app.route("/") -def home_page(): +@app.route("/subclass_objects") +def subclass_objects(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + return Movie.objects(__raw__=json_search) + +@app.route("/get_db_find") +def get_db_find(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) retrieved_db = db.get_db() - data = retrieved_db["Movie"].find({'name': json_search}) + return retrieved_db["Movie"].find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py deleted file mode 100644 index f55f3270f47..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_bad.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Flask, request -from flask_mongoengine import MongoEngine -import json - -app = Flask(__name__) -app.config.from_pyfile('the-config.cfg') -db = MongoEngine(app) - -class Movie(db.Document): - title = db.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - data = Movie.objects(__raw__=json_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py deleted file mode 100644 index c0a03d718aa..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_db_document_subclass_good.py +++ /dev/null @@ -1,26 +0,0 @@ -from flask import Flask, request -from flask_mongoengine import MongoEngine -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) -app.config.from_pyfile('the-config.cfg') -db = MongoEngine(app) - -class Movie(db.Document): - title = db.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - data = Movie.objects(__raw__=safe_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py similarity index 68% rename from python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py rename to python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index 5837eaa2d58..abfcfaba48c 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_get_db_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -15,8 +15,16 @@ class Movie(db.Document): Movie(title='test').save() -@app.route("/") -def home_page(): +@app.route("/subclass_objects") +def subclass_objects(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + return Movie.objects(__raw__=safe_search) + +@app.route("/get_db_find") +def get_db_find(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py new file mode 100644 index 00000000000..81800425e46 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py @@ -0,0 +1,64 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + + +Movie(title='test').save() + + +@app.route("/connect_find") +def connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.connect('mydb') + return db.movie.find({'name': json_search}) + +@app.route("/connection_connect_find") +def connection_connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = connect('mydb') + return db.movie.find({'name': json_search}) + +@app.route("/get_db_find") +def get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.get_db() + return db.movie.find({'name': json_search}) + +@app.route("/connection_get_db_find") +def connection_get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = get_db() + return db.movie.find({'name': json_search}) + +@app.route("/subclass_objects") +def subclass_objects(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + return Movie.objects(__raw__=json_search) + +@app.route("/subscript_find") +def subscript_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.connect('mydb') + return db['movie'].find({'name': json_search}) + +# if __name__ == "__main__": +# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py deleted file mode 100644 index 1443f72720d..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_bad.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Flask, request -import mongoengine as me -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = me.connect('mydb') - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py deleted file mode 100644 index 219503a213a..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_good.py +++ /dev/null @@ -1,26 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.connect('mydb') - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py deleted file mode 100644 index 398199bc0cd..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_bad.py +++ /dev/null @@ -1,25 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongoengine.connection import get_db, connect -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = connect('mydb') - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py deleted file mode 100644 index 51b801468ce..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_connect_via_connection_good.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongoengine.connection import get_db, connect -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = connect('mydb') - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py deleted file mode 100644 index 95467393541..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_bad.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask import Flask, request -import mongoengine as me -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - data = Movie.objects(__raw__=json_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py deleted file mode 100644 index c852d550464..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_document_subclass_good.py +++ /dev/null @@ -1,25 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - data = Movie.objects(__raw__=safe_search) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py deleted file mode 100644 index 8b1d8ebb6fb..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_bad.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Flask, request -import mongoengine as me -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = me.get_db() - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py deleted file mode 100644 index 08c43b4d209..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_good.py +++ /dev/null @@ -1,26 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.get_db() - data = db.movie.find({'name': safe_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py deleted file mode 100644 index 76b32a69572..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_bad.py +++ /dev/null @@ -1,25 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongoengine.connection import get_db, connect -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = get_db() - data = db.movie.find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py deleted file mode 100644 index 9ac27c8c54a..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_get_db_via_connection_good.py +++ /dev/null @@ -1,27 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongoengine.connection import get_db, connect -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = get_db() - data = db.movie.find({'name': safe_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py new file mode 100644 index 00000000000..14bc3e6c2ea --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -0,0 +1,68 @@ +from flask import Flask, request +import mongoengine as me +from mongoengine.connection import get_db, connect +from mongosanitizer.sanitizer import sanitize +import json + +app = Flask(__name__) + + +class Movie(me.Document): + title = me.StringField(required=True) + + +Movie(title='test').save() + + +@app.route("/connect_find") +def connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.connect('mydb') + return db.movie.find({'name': json_search}) + +@app.route("/connection_connect_find") +def connection_connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = connect('mydb') + return db.movie.find({'name': json_search}) + +@app.route("/subclass_objects") +def subclass_objects(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + return Movie.objects(__raw__=safe_search) + +@app.route("/get_db_find") +def get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.get_db() + return db.movie.find({'name': safe_search}) + +@app.route("/connection_get_db_find") +def connection_get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = get_db() + return db.movie.find({'name': safe_search}) + +@app.route("/subscript_find") +def subscript_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.connect('mydb') + return db['movie'].find({'name': safe_search}) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py deleted file mode 100644 index 96e08418b24..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_bad.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Flask, request -import mongoengine as me -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = me.connect('mydb') - data = db['movie'].find({'name': json_search}) - -# if __name__ == "__main__": -# app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py deleted file mode 100644 index e9be8dd3e3c..00000000000 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_subscript_good.py +++ /dev/null @@ -1,26 +0,0 @@ -from flask import Flask, request -import mongoengine as me -from mongosanitizer.sanitizer import sanitize -import json - -app = Flask(__name__) - - -class Movie(me.Document): - title = me.StringField(required=True) - - -Movie(title='test').save() - - -@app.route("/") -def home_page(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.connect('mydb') - data = db['movie'].find({'name': safe_search}) - -# if __name__ == "__main__": -# app.run(debug=True) From 3fd11298958ee4d8bb18806faebcacd59433818e Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 28 Jun 2021 20:18:31 +0200 Subject: [PATCH 101/429] Delete trivial tests --- .../Security/CWE-943/flask_mongoengine_good.py | 2 +- .../Security/CWE-943/flask_pymongo_bad.py | 2 +- .../Security/CWE-943/flask_pymongo_good.py | 2 +- .../Security/CWE-943/mongoengine_bad.py | 16 ---------------- .../Security/CWE-943/mongoengine_good.py | 18 ------------------ .../Security/CWE-943/pymongo_bad.py | 2 +- .../Security/CWE-943/pymongo_good.py | 2 +- 7 files changed, 5 insertions(+), 39 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index abfcfaba48c..04f82bf0a92 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -30,7 +30,7 @@ def get_db_find(): safe_search = sanitize(json_search) retrieved_db = db.get_db() - data = retrieved_db["Movie"].find({'name': safe_search}) + return retrieved_db["Movie"].find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py index 93c570fbe58..0c1023971da 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_bad.py @@ -11,7 +11,7 @@ def home_page(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - data = mongo.db.user.find({'name': json_search}) + return mongo.db.user.find({'name': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py index 29af42d8536..6576ba88af8 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_pymongo_good.py @@ -13,7 +13,7 @@ def home_page(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - data = mongo.db.user.find({'name': safe_search}) + return mongo.db.user.find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py index 81800425e46..fd5dd7e4bb7 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py @@ -21,22 +21,6 @@ def connect_find(): db = me.connect('mydb') return db.movie.find({'name': json_search}) -@app.route("/connection_connect_find") -def connection_connect_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = connect('mydb') - return db.movie.find({'name': json_search}) - -@app.route("/get_db_find") -def get_db_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - - db = me.get_db() - return db.movie.find({'name': json_search}) - @app.route("/connection_get_db_find") def connection_get_db_find(): unsafe_search = request.args['search'] diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py index 14bc3e6c2ea..6a874e6b698 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -23,15 +23,6 @@ def connect_find(): db = me.connect('mydb') return db.movie.find({'name': json_search}) -@app.route("/connection_connect_find") -def connection_connect_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = connect('mydb') - return db.movie.find({'name': json_search}) - @app.route("/subclass_objects") def subclass_objects(): unsafe_search = request.args['search'] @@ -40,15 +31,6 @@ def subclass_objects(): return Movie.objects(__raw__=safe_search) -@app.route("/get_db_find") -def get_db_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.get_db() - return db.movie.find({'name': safe_search}) - @app.route("/connection_get_db_find") def connection_get_db_find(): unsafe_search = request.args['search'] diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py index e0fc3514d73..da16df828b8 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_bad.py @@ -11,7 +11,7 @@ def home_page(): unsafe_search = request.args['search'] json_search = json.loads(unsafe_search) - data = client.db.collection.find_one({'data': json_search}) + return client.db.collection.find_one({'data': json_search}) # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py index 0e52609fd7d..5b112e12385 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/pymongo_good.py @@ -13,7 +13,7 @@ def home_page(): json_search = json.loads(unsafe_search) safe_search = sanitize(json_search) - data = client.db.collection.find_one({'data': safe_search}) + return client.db.collection.find_one({'data': safe_search}) # if __name__ == "__main__": # app.run(debug=True) From 68c683189a902d403f3f6801e3ce283314528e8a Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 28 Jun 2021 20:55:49 +0200 Subject: [PATCH 102/429] Polish documentation, `mongoCollectionMethod()` and update `.expected` --- .../semmle/python/frameworks/NoSQL.qll | 94 +++++++++++++++++-- .../Security/CWE-943/NoSQLInjection.expected | 74 ++++----------- 2 files changed, 104 insertions(+), 64 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll index 2b6fbb1f752..f7ba8390677 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll @@ -11,35 +11,49 @@ private import experimental.semmle.python.Concepts private import semmle.python.ApiGraphs private module NoSQL { - /** API Nodes returning `Mongo` instances. */ + // API Nodes returning `Mongo` instances. + /** Gets a reference to `pymongo.MongoClient` */ private API::Node pyMongo() { result = API::moduleImport("pymongo").getMember("MongoClient").getReturn() } + /** Gets a reference to `flask_pymongo.PyMongo` */ private API::Node flask_PyMongo() { result = API::moduleImport("flask_pymongo").getMember("PyMongo").getReturn() } + /** Gets a reference to `mongoengine` */ private API::Node mongoEngine() { result = API::moduleImport("mongoengine") } + /** Gets a reference to `flask_mongoengine.MongoEngine` */ private API::Node flask_MongoEngine() { result = API::moduleImport("flask_mongoengine").getMember("MongoEngine").getReturn() } - /** Gets a reference to a initialized `Mongo` instance. */ + /** + * Gets a reference to a initialized `Mongo` instance. + * See `pyMongo()`, `flask_PyMongo()` + */ private API::Node mongoInstance() { result = pyMongo() or result = flask_PyMongo() } - /** Gets a reference to a initialized `Mongo` DB instance. */ + /** + * Gets a reference to a initialized `Mongo` DB instance. + * See `mongoEngine()`, `flask_MongoEngine()` + */ private API::Node mongoDBInstance() { result = mongoEngine().getMember(["get_db", "connect"]).getReturn() or result = mongoEngine().getMember("connection").getMember(["get_db", "connect"]).getReturn() or result = flask_MongoEngine().getMember("get_db").getReturn() } - /** Gets a reference to a `Mongo` DB use. */ + /** + * Gets a reference to a `Mongo` DB use. + * + * See `mongoInstance()`, `mongoDBInstance()`. + */ private DataFlow::LocalSourceNode mongoDB(DataFlow::TypeTracker t) { t.start() and ( @@ -56,10 +70,24 @@ private module NoSQL { exists(DataFlow::TypeTracker t2 | result = mongoDB(t2).track(t2, t)) } - /** Gets a reference to a `Mongo` DB use. */ + /** + * Gets a reference to a `Mongo` DB use. + * + * ```py + * from flask_pymongo import PyMongo + * mongo = PyMongo(app) + * mongo.db.user.find({'name': safe_search}) + * ``` + * + * `mongo.db` would be a `use` of a `Mongo` instance, and so the result. + */ private DataFlow::Node mongoDB() { mongoDB(DataFlow::TypeTracker::end()).flowsTo(result) } - /** Gets a reference to a `Mongo` collection use. */ + /** + * Gets a reference to a `Mongo` collection use. + * + * See `mongoDB()`. + */ private DataFlow::LocalSourceNode mongoCollection(DataFlow::TypeTracker t) { t.start() and ( @@ -73,7 +101,17 @@ private module NoSQL { exists(DataFlow::TypeTracker t2 | result = mongoCollection(t2).track(t2, t)) } - /** Gets a reference to a `Mongo` collection use. */ + /** + * Gets a reference to a `Mongo` collection use. + * + * ```py + * from flask_pymongo import PyMongo + * mongo = PyMongo(app) + * mongo.db.user.find({'name': safe_search}) + * ``` + * + * `mongo.db.user` would be a `use` of a `Mongo` collection, and so the result. + */ private DataFlow::Node mongoCollection() { mongoCollection(DataFlow::TypeTracker::end()).flowsTo(result) } @@ -88,19 +126,54 @@ private module NoSQL { } } - /** Gets a reference to a `Mongo` collection method. */ + /** + * Gets a reference to a `Mongo` collection method. + * + * ```py + * from flask_pymongo import PyMongo + * mongo = PyMongo(app) + * mongo.db.user.find({'name': safe_search}) + * ``` + * + * `mongo.db.user.find` would be a collection method, and so the result. + */ private DataFlow::Node mongoCollectionMethod() { - mongoCollection() in [result.(DataFlow::AttrRead), result.(DataFlow::AttrRead).getObject()] and + mongoCollection() = result.(DataFlow::AttrRead).getObject() and result.(DataFlow::AttrRead).getAttributeName() instanceof MongoCollectionMethodNames } - /** Gets a reference to a `Mongo` collection method call */ + /** + * Gets a reference to a `Mongo` collection method call + * + * ```py + * from flask_pymongo import PyMongo + * mongo = PyMongo(app) + * mongo.db.user.find({'name': safe_search}) + * ``` + * + * `mongo.db.user.find({'name': safe_search})` would be a collection method call, and so the result. + */ private class MongoCollectionCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { MongoCollectionCall() { this.getFunction() = mongoCollectionMethod() } override DataFlow::Node getQuery() { result = this.getArg(0) } } + /** + * Gets a reference to a call from a class whose base is a reference to `mongoEngine()` or `flask_MongoEngine()`'s + * `Document` or `EmbeddedDocument` objects and its attribute is `objects`. + * + * ```py + * from flask_mongoengine import MongoEngine + * db = MongoEngine(app) + * class Movie(db.Document): + * title = db.StringField(required=True) + * + * Movie.objects(__raw__=json_search) + * ``` + * + * `Movie.objects(__raw__=json_search)` would be the result. + */ private class MongoEngineObjectsCall extends DataFlow::CallCfgNode, NoSQLQuery::Range { MongoEngineObjectsCall() { this = @@ -114,6 +187,7 @@ private module NoSQL { override DataFlow::Node getQuery() { result = this.getArgByName(_) } } + /** Gets a reference to `mongosanitizer.sanitizer.sanitize` */ private class MongoSanitizerCall extends DataFlow::CallCfgNode, NoSQLSanitizer::Range { MongoSanitizerCall() { this = diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 10c1f852df5..80c54422542 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -31,37 +31,23 @@ edges | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | -| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | -| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | -| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | +| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | +| mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | | mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | | mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:36:21:36:27 | ControlFlowNode for request | mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | mongoengine_good.py:37:19:37:43 | ControlFlowNode for Attribute() | | mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -111,22 +97,12 @@ nodes | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | -| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -135,22 +111,14 @@ nodes | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:36:21:36:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:37:19:37:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -166,8 +134,6 @@ nodes | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From 350440897c753a3a948a8a4e10171d413997a435 Mon Sep 17 00:00:00 2001 From: Jorge <46056498+jorgectf@users.noreply.github.com> Date: Mon, 28 Jun 2021 21:02:40 +0200 Subject: [PATCH 103/429] Apply suggestions from code review Update `xmltodict` format and delete `ujson` modeling. Co-authored-by: Rasmus Wriedt Larsen --- .../semmle/python/frameworks/Stdlib.qll | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index 7db995220d4..d16acdcb183 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -119,27 +119,5 @@ private class XmlToDictParseCall extends Decoding::Range, DataFlow::CallCfgNode override DataFlow::Node getOutput() { result = this } - override string getFormat() { result = "JSON" } -} - -// --------------------------------------------------------------------------- -// ujson -// --------------------------------------------------------------------------- -/** Gets a reference to the `ujson` module. */ -API::Node ujson() { result = API::moduleImport("ujson") } - -/** - * A call to `ujson.loads` - * See https://pypi.org/project/ujson/#usage - */ -private class UltraJsonLoadsCall extends Decoding::Range, DataFlow::CallCfgNode { - UltraJsonLoadsCall() { this = ujson().getMember("loads").getACall() } - - override predicate mayExecuteInput() { none() } - - override DataFlow::Node getAnInput() { result = this.getArg(0) } - - override DataFlow::Node getOutput() { result = this } - - override string getFormat() { result = "JSON" } + override string getFormat() { result = "XML" } } From 51395d155f68b99c1210689c675e80c2389fa0e1 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Mon, 28 Jun 2021 21:08:43 +0200 Subject: [PATCH 104/429] Move `xmltodict` to its own file under `frameworks/` --- .../semmle/python/frameworks/Stdlib.qll | 23 ------------- .../semmle/python/frameworks/Xmltodict.qll | 34 +++++++++++++++++++ 2 files changed, 34 insertions(+), 23 deletions(-) create mode 100644 python/ql/src/experimental/semmle/python/frameworks/Xmltodict.qll diff --git a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll index d16acdcb183..4f3457e0a99 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Stdlib.qll @@ -8,7 +8,6 @@ private import semmle.python.dataflow.new.DataFlow private import semmle.python.dataflow.new.TaintTracking private import semmle.python.dataflow.new.RemoteFlowSources private import experimental.semmle.python.Concepts -private import semmle.python.Concepts private import semmle.python.ApiGraphs /** @@ -99,25 +98,3 @@ private module Re { override DataFlow::Node getRegexNode() { result = regexNode } } } - -// --------------------------------------------------------------------------- -// xmltodict -// --------------------------------------------------------------------------- -/** Gets a reference to the `xmltodict` module. */ -API::Node xmltodict() { result = API::moduleImport("xmltodict") } - -/** - * A call to `xmltodict.parse` - * See https://github.com/martinblech/xmltodict/blob/ae19c452ca000bf243bfc16274c060bf3bf7cf51/xmltodict.py#L198 - */ -private class XmlToDictParseCall extends Decoding::Range, DataFlow::CallCfgNode { - XmlToDictParseCall() { this = xmltodict().getMember("parse").getACall() } - - override predicate mayExecuteInput() { none() } - - override DataFlow::Node getAnInput() { result = this.getArg(0) } - - override DataFlow::Node getOutput() { result = this } - - override string getFormat() { result = "XML" } -} diff --git a/python/ql/src/experimental/semmle/python/frameworks/Xmltodict.qll b/python/ql/src/experimental/semmle/python/frameworks/Xmltodict.qll new file mode 100644 index 00000000000..353130fdc9c --- /dev/null +++ b/python/ql/src/experimental/semmle/python/frameworks/Xmltodict.qll @@ -0,0 +1,34 @@ +/** + * Provides classes modeling security-relevant aspects of the `xmltodict` PyPI package. + * See https://pypi.org/project/xmltodict/ + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.Concepts +private import semmle.python.ApiGraphs + +/** + * Provides models for the `xmltodict` PyPI package. + * See https://pypi.org/project/xmltodict/ + */ +private module XmlToDictModel { + /** Gets a reference to the `xmltodict` module. */ + API::Node xmltodict() { result = API::moduleImport("xmltodict") } + + /** + * A call to `xmltodict.parse` + * See https://github.com/martinblech/xmltodict/blob/ae19c452ca000bf243bfc16274c060bf3bf7cf51/xmltodict.py#L198 + */ + private class XmlToDictParseCall extends Decoding::Range, DataFlow::CallCfgNode { + XmlToDictParseCall() { this = xmltodict().getMember("parse").getACall() } + + override predicate mayExecuteInput() { none() } + + override DataFlow::Node getAnInput() { result = this.getArg(0) } + + override DataFlow::Node getOutput() { result = this } + + override string getFormat() { result = "XML" } + } +} From 0819090fcbc78c0487370d0683d9449a2ad8f183 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 29 Jun 2021 16:53:32 +0200 Subject: [PATCH 105/429] Fix qldocs typo --- .../src/experimental/semmle/python/frameworks/NoSQL.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll index f7ba8390677..545a7e9d6a5 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/NoSQL.qll @@ -31,7 +31,7 @@ private module NoSQL { } /** - * Gets a reference to a initialized `Mongo` instance. + * Gets a reference to an initialized `Mongo` instance. * See `pyMongo()`, `flask_PyMongo()` */ private API::Node mongoInstance() { @@ -40,7 +40,7 @@ private module NoSQL { } /** - * Gets a reference to a initialized `Mongo` DB instance. + * Gets a reference to an initialized `Mongo` DB instance. * See `mongoEngine()`, `flask_MongoEngine()` */ private API::Node mongoDBInstance() { @@ -79,7 +79,7 @@ private module NoSQL { * mongo.db.user.find({'name': safe_search}) * ``` * - * `mongo.db` would be a `use` of a `Mongo` instance, and so the result. + * `mongo.db` would be a use of a `Mongo` instance, and so the result. */ private DataFlow::Node mongoDB() { mongoDB(DataFlow::TypeTracker::end()).flowsTo(result) } @@ -110,7 +110,7 @@ private module NoSQL { * mongo.db.user.find({'name': safe_search}) * ``` * - * `mongo.db.user` would be a `use` of a `Mongo` collection, and so the result. + * `mongo.db.user` would be a use of a `Mongo` collection, and so the result. */ private DataFlow::Node mongoCollection() { mongoCollection(DataFlow::TypeTracker::end()).flowsTo(result) From 9a8d1f8e0f7327aeb61faa14d28dea5e0e5a2d1b Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 29 Jun 2021 16:53:44 +0200 Subject: [PATCH 106/429] Take back non-trivial tests --- .../Security/CWE-943/mongoengine_bad.py | 16 ++++++++++++++++ .../Security/CWE-943/mongoengine_good.py | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py index fd5dd7e4bb7..81800425e46 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_bad.py @@ -21,6 +21,22 @@ def connect_find(): db = me.connect('mydb') return db.movie.find({'name': json_search}) +@app.route("/connection_connect_find") +def connection_connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = connect('mydb') + return db.movie.find({'name': json_search}) + +@app.route("/get_db_find") +def get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + + db = me.get_db() + return db.movie.find({'name': json_search}) + @app.route("/connection_get_db_find") def connection_get_db_find(): unsafe_search = request.args['search'] diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py index 6a874e6b698..14bc3e6c2ea 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -23,6 +23,15 @@ def connect_find(): db = me.connect('mydb') return db.movie.find({'name': json_search}) +@app.route("/connection_connect_find") +def connection_connect_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = connect('mydb') + return db.movie.find({'name': json_search}) + @app.route("/subclass_objects") def subclass_objects(): unsafe_search = request.args['search'] @@ -31,6 +40,15 @@ def subclass_objects(): return Movie.objects(__raw__=safe_search) +@app.route("/get_db_find") +def get_db_find(): + unsafe_search = request.args['search'] + json_search = json.loads(unsafe_search) + safe_search = sanitize(json_search) + + db = me.get_db() + return db.movie.find({'name': safe_search}) + @app.route("/connection_get_db_find") def connection_get_db_find(): unsafe_search = request.args['search'] From 621a810b7b83a6af0adef87e2940007fd3735e99 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 29 Jun 2021 16:53:53 +0200 Subject: [PATCH 107/429] Update `.expected` --- .../Security/CWE-943/NoSQLInjection.expected | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 80c54422542..10c1f852df5 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -31,23 +31,37 @@ edges | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | -| mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | -| mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | -| mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | -| mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | +| mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | +| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | +| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | +| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | +| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | | mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | | mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:36:21:36:27 | ControlFlowNode for request | mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | mongoengine_good.py:37:19:37:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | | mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | +| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | +| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | +| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -97,12 +111,22 @@ nodes | mongoengine_bad.py:34:21:34:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_bad.py:34:21:34:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_bad.py:35:19:35:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | -| mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_bad.py:41:21:41:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_bad.py:41:21:41:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_bad.py:42:19:42:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:42:21:42:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:42:21:42:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:43:19:43:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:50:21:50:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:50:21:50:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:51:19:51:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | semmle.label | ControlFlowNode for json_search | +| mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_bad.py:57:21:57:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | | mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -111,14 +135,22 @@ nodes | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:36:21:36:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:36:21:36:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:36:21:36:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:37:19:37:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -134,6 +166,8 @@ nodes | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:37:34:37:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:45:29:45:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:41:21:41:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_bad.py:14:42:14:62 | ControlFlowNode for Dict | This | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | From e02a63a27a5309312653593c7a62fe3e5a1055f6 Mon Sep 17 00:00:00 2001 From: jorgectf Date: Tue, 29 Jun 2021 23:03:41 +0200 Subject: [PATCH 108/429] Delete trivial `*_good.py` tests --- .../CWE-943/flask_mongoengine_good.py | 9 ---- .../Security/CWE-943/mongoengine_good.py | 45 +------------------ 2 files changed, 2 insertions(+), 52 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py index 04f82bf0a92..29a2c75d664 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/flask_mongoengine_good.py @@ -23,14 +23,5 @@ def subclass_objects(): return Movie.objects(__raw__=safe_search) -@app.route("/get_db_find") -def get_db_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - retrieved_db = db.get_db() - return retrieved_db["Movie"].find({'name': safe_search}) - # if __name__ == "__main__": # app.run(debug=True) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py index 14bc3e6c2ea..1ece6997a89 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -23,46 +23,5 @@ def connect_find(): db = me.connect('mydb') return db.movie.find({'name': json_search}) -@app.route("/connection_connect_find") -def connection_connect_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = connect('mydb') - return db.movie.find({'name': json_search}) - -@app.route("/subclass_objects") -def subclass_objects(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - return Movie.objects(__raw__=safe_search) - -@app.route("/get_db_find") -def get_db_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.get_db() - return db.movie.find({'name': safe_search}) - -@app.route("/connection_get_db_find") -def connection_get_db_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = get_db() - return db.movie.find({'name': safe_search}) - -@app.route("/subscript_find") -def subscript_find(): - unsafe_search = request.args['search'] - json_search = json.loads(unsafe_search) - safe_search = sanitize(json_search) - - db = me.connect('mydb') - return db['movie'].find({'name': safe_search}) +# if __name__ == "__main__": +# app.run(debug=True) From c3ac3ca41c3f7d3b9f332e977701dc6642b09188 Mon Sep 17 00:00:00 2001 From: edvraa Date: Mon, 14 Jun 2021 22:38:27 +0300 Subject: [PATCH 109/429] FsPickler --- .../dataflow/UnsafeDeserialization.qll | 48 ++++++++ .../csharp/serialization/Deserializers.qll | 111 ++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 407d7b22bbc..bb71ffa7b1d 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -750,4 +750,52 @@ module UnsafeDeserialization { ) } } + + /** FsPickler */ + private predicate isWeakTypeFsPicklerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof FsPicklerSerializerClassUnPickleUntypedMethod or + m instanceof FsPicklerSerializerClassDeserializeUntypedMethod or + m instanceof FsPicklerSerializerClassDeserializeSequenceUntypedMethod + ) and + not mc.getArgument(0).hasValue() + } + + abstract private class FsPicklerWeakTypeSink extends ConstructorOrStaticMethodSink { } + + private class FsPicklerDeserializeWeakTypeMethodSink extends FsPicklerWeakTypeSink { + FsPicklerDeserializeWeakTypeMethodSink() { + exists(MethodCall mc, Method m | + isWeakTypeFsPicklerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } + + private predicate isStrongTypeFsPicklerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof FsPicklerSerializerClassDeserializeMethod or + m instanceof FsPicklerSerializerClassDeserializeSequenceMethod or + m instanceof FsPicklerSerializerClasDeserializeSiftedMethod or + m instanceof FsPicklerSerializerClassUnPickleMethod or + m instanceof FsPicklerSerializerClassUnPickleSiftedMethod or + m instanceof CsPicklerSerializerClassDeserializeMethod or + m instanceof CsPicklerSerializerClassUnPickleMethod or + m instanceof CsPicklerSerializerClassUnPickleOfStringMethod + ) and + not mc.getArgument(0).hasValue() + } + + abstract private class FsPicklerStrongTypeSink extends InstanceMethodSink { } + + private class FsPicklerDeserializeStrongTypeMethodSink extends FsPicklerStrongTypeSink { + FsPicklerDeserializeStrongTypeMethodSink() { + exists(MethodCall mc, Method m | + isStrongTypeFsPicklerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } + } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 58b6375bc13..5a076703afc 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -18,6 +18,12 @@ class StrongTypeDeserializer extends Class { this instanceof DataContractSerializerClass or this instanceof XmlMessageFormatterClass + or + this instanceof FsPicklerSerializerClass + or + this instanceof CsPicklerSerializerClass + or + this instanceof CsPicklerTextSerializerClass } } @@ -513,3 +519,108 @@ class ServiceStackTextXmlSerializerDeserializeFromStreamMethod extends Method, U this.isStatic() } } + +/** MBrace.FsPickler.FsPicklerSerializer */ +private class FsPicklerSerializerClass extends Class { + FsPicklerSerializerClass() { this.hasQualifiedName("MBrace.FsPickler.FsPicklerSerializer") } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.Deserialize` method */ +class FsPicklerSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassDeserializeMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("Deserialize") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.DeserializeSequence` method */ +class FsPicklerSerializerClassDeserializeSequenceMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassDeserializeSequenceMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("DeserializeSequence") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.DeserializeSifted` method */ +class FsPicklerSerializerClasDeserializeSiftedMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClasDeserializeSiftedMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("DeserializeSifted") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.UnPickle` method */ +class FsPicklerSerializerClassUnPickleMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassUnPickleMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("UnPickle") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.UnPickleSifted` method */ +class FsPicklerSerializerClassUnPickleSiftedMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassUnPickleSiftedMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("UnPickleSifted") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.DeserializeUntyped` method */ +class FsPicklerSerializerClassDeserializeUntypedMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassDeserializeUntypedMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("DeserializeUntyped") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.DeserializeSequenceUntyped` method */ +class FsPicklerSerializerClassDeserializeSequenceUntypedMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassDeserializeSequenceUntypedMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("DeserializeSequenceUntyped") + } +} + +/** `MBrace.FsPickler.FsPicklerSerializer.UnPickleUntyped` method */ +class FsPicklerSerializerClassUnPickleUntypedMethod extends Method, UnsafeDeserializer { + FsPicklerSerializerClassUnPickleUntypedMethod() { + this.getDeclaringType().getBaseClass*() instanceof FsPicklerSerializerClass and + this.hasName("UnPickleUntyped") + } +} + +/** MBrace.CsPickler.CsPicklerSerializer */ +private class CsPicklerSerializerClass extends Class { + CsPicklerSerializerClass() { this.hasQualifiedName("MBrace.CsPickler.CsPicklerSerializer") } +} + +/** `MBrace.FsPickler.CsPicklerSerializer.Deserialize` method */ +class CsPicklerSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { + CsPicklerSerializerClassDeserializeMethod() { + this.getDeclaringType().getBaseClass*() instanceof CsPicklerSerializerClass and + this.hasName("Deserialize") + } +} + +/** `MBrace.FsPickler.CsPicklerSerializer.UnPickle` method */ +class CsPicklerSerializerClassUnPickleMethod extends Method, UnsafeDeserializer { + CsPicklerSerializerClassUnPickleMethod() { + this.getDeclaringType().getBaseClass*() instanceof CsPicklerSerializerClass and + this.hasName("UnPickle") + } +} + +/** MBrace.CsPickler.CsPicklerTextSerializer */ +private class CsPicklerTextSerializerClass extends Class { + CsPicklerTextSerializerClass() { + this.hasQualifiedName("MBrace.CsPickler.CsPicklerTextSerializer") + } +} + +/** `MBrace.FsPickler.CsPicklerTextSerializer.UnPickleOfString` method */ +class CsPicklerSerializerClassUnPickleOfStringMethod extends Method, UnsafeDeserializer { + CsPicklerSerializerClassUnPickleOfStringMethod() { + this.getDeclaringType().getBaseClass*() instanceof CsPicklerTextSerializerClass and + this.hasName("UnPickleOfString") + } +} From 1e4409f9edf1cb34c7e5b0b9665ce128f554d109 Mon Sep 17 00:00:00 2001 From: edvraa Date: Mon, 14 Jun 2021 23:26:28 +0300 Subject: [PATCH 110/429] SharpSerializer --- .../security/dataflow/UnsafeDeserialization.qll | 14 ++++++++++++++ .../code/csharp/serialization/Deserializers.qll | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index bb71ffa7b1d..573b4eaf461 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -798,4 +798,18 @@ module UnsafeDeserialization { ) } } + + /** SharpSerializer */ + private class SharpSerializerDeserializeMethodSink extends InstanceMethodSink { + SharpSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof SharpSerializerClassDeserializeMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } + } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 5a076703afc..012c74bbe9a 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -63,6 +63,8 @@ class WeakTypeDeserializer extends Class { this instanceof ServiceStackTextCsvSerializerClass or this instanceof ServiceStackTextXmlSerializerClass + or + this instanceof SharpSerializerClass } } @@ -624,3 +626,16 @@ class CsPicklerSerializerClassUnPickleOfStringMethod extends Method, UnsafeDeser this.hasName("UnPickleOfString") } } + +/** Polenter.Serialization.SharpSerializer */ +private class SharpSerializerClass extends Class { + SharpSerializerClass() { this.hasQualifiedName("Polenter.Serialization.SharpSerializer") } +} + +/** `Polenter.Serialization.SharpSerializer.Deserialize` method */ +class SharpSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { + SharpSerializerClassDeserializeMethod() { + this.getDeclaringType().getBaseClass*() instanceof SharpSerializerClass and + this.hasName("Deserialize") + } +} From f4cb6c50c00c4e3f7d9240a8a930f4872c0911b8 Mon Sep 17 00:00:00 2001 From: edvraa Date: Tue, 15 Jun 2021 12:23:52 +0300 Subject: [PATCH 111/429] YamlDotNet --- .../dataflow/UnsafeDeserialization.qll | 14 ++++++++++++++ .../csharp/serialization/Deserializers.qll | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 573b4eaf461..d56935534ca 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -812,4 +812,18 @@ module UnsafeDeserialization { ) } } + + /** YamlDotNet */ + private class YamlDotNetDeserializerDeserializeMethodSink extends ConstructorOrStaticMethodSink { + YamlDotNetDeserializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof YamlDotNetDeserializerClasseserializeMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } + } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 012c74bbe9a..48dbe6f70f7 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -65,6 +65,8 @@ class WeakTypeDeserializer extends Class { this instanceof ServiceStackTextXmlSerializerClass or this instanceof SharpSerializerClass + or + this instanceof YamlDotNetDeserializerClass } } @@ -639,3 +641,19 @@ class SharpSerializerClassDeserializeMethod extends Method, UnsafeDeserializer { this.hasName("Deserialize") } } + +/** YamlDotNet.Serialization.Deserializer */ +private class YamlDotNetDeserializerClass extends Class { + YamlDotNetDeserializerClass() { this.hasQualifiedName("YamlDotNet.Serialization.Deserializer") } +} + +/** `YamlDotNet.Serialization.Deserializer.Deserialize` method */ +class YamlDotNetDeserializerClasseserializeMethod extends Method, UnsafeDeserializer { + YamlDotNetDeserializerClasseserializeMethod() { + exists(YamlDotNetDeserializerClass c | + this.getDeclaringType().getBaseClass*() = c and + this.hasName("Deserialize") and + c.getALocation().(Assembly).getVersion().getMajor() < 5 + ) + } +} From a0942e0360e70da7cff65e039e5f25229a7054a2 Mon Sep 17 00:00:00 2001 From: edvraa Date: Mon, 12 Jul 2021 15:10:21 +0300 Subject: [PATCH 112/429] JsonConvert --- .../UnsafeDeserializationUntrustedInput.ql | 11 +++ .../semmle/code/csharp/frameworks/JsonNET.qll | 13 +++ .../dataflow/UnsafeDeserialization.qll | 88 ++++++++++++++++++- .../csharp/serialization/Deserializers.qll | 12 +++ 4 files changed, 122 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index 963896e6d66..e8ee6bbe058 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -46,5 +46,16 @@ where exists(TaintToConstructorOrStaticMethodTrackingConfig taintTracking2 | taintTracking2.hasFlowPath(userInput, deserializeCallArg) ) + or + // JsonConvert static method call, but with additional unsafe typename tracking + exists( + JsonConvertTrackingConfig taintTrackingJsonConvert, TypeNameTrackingConfig typenameTracking, + DataFlow::PathNode settingsCallArg + | + taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and + typenameTracking.hasFlowPath(_, settingsCallArg) and + deserializeCallArg.getNode().asExpr().getParent() = + settingsCallArg.getNode().asExpr().getParent() + ) select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.", userInput, "User-provided data" diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/JsonNET.qll b/csharp/ql/src/semmle/code/csharp/frameworks/JsonNET.qll index 54019d13216..abd820bdfe4 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/JsonNET.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/JsonNET.qll @@ -17,6 +17,19 @@ module JsonNET { JsonClass() { this.getParent() instanceof JsonNETNamespace } } + /** Newtonsoft.Json.TypeNameHandling enum */ + class TypeNameHandlingEnum extends Enum { + TypeNameHandlingEnum() { + this.getParent() instanceof JsonNETNamespace and + this.hasName("TypeNameHandling") + } + } + + /** Newtonsoft.Json.JsonSerializerSettings class */ + class JsonSerializerSettingsClass extends JsonClass { + JsonSerializerSettingsClass() { this.hasName("JsonSerializerSettings") } + } + /** The class `Newtonsoft.Json.JsonConvert`. */ class JsonConvertClass extends JsonClass, LibraryTypeDataFlow { JsonConvertClass() { this.hasName("JsonConvert") } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index d56935534ca..69aaab1fed2 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -59,7 +59,7 @@ module UnsafeDeserialization { * User input to object method call deserialization flow tracking. */ class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration { - TaintToObjectMethodTrackingConfig() { this = "UnsafeDeserialization1" } + TaintToObjectMethodTrackingConfig() { this = "TaintToObjectMethodTrackingConfig" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -68,11 +68,81 @@ module UnsafeDeserialization { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } + /** + * User input to `JsonConvert` call deserialization flow tracking. + */ + class JsonConvertTrackingConfig extends TaintTracking::Configuration { + JsonConvertTrackingConfig() { this = "JsonConvertTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof NewtonsoftJsonConvertDeserializeObjectMethodSink + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + } + + /** + * Tracks unsafe `TypeNameHandling` setting to `JsonConvert` call + */ + class TypeNameTrackingConfig extends DataFlow::Configuration { + TypeNameTrackingConfig() { this = "TypeNameTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { + ( + source.asExpr() instanceof MemberConstantAccess and + source.getType() instanceof TypeNameHandlingEnum + or + source.asExpr() instanceof IntegerLiteral + ) and + source.asExpr().hasValue() and + not source.asExpr().getValue() = "0" + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m, Expr expr | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod + ) and + expr = mc.getAnArgument() and + sink.asExpr() = expr and + expr.getType() instanceof JsonSerializerSettingsClass + ) + } + + override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.asExpr() instanceof IntegerLiteral and + node2.asExpr().(CastExpr).getExpr() = node1.asExpr() + or + node1.getType() instanceof TypeNameHandlingEnum and + exists(PropertyWrite pw, Property p, Assignment a | + a.getLValue() = pw and + pw.getProperty() = p and + p.getDeclaringType() instanceof JsonSerializerSettingsClass and + p.hasName("TypeNameHandling") and + ( + node1.asExpr() = a.getRValue() and + node2.asExpr() = pw.getQualifier() + or + exists(ObjectInitializer oi | + node1.asExpr() = oi.getAMemberInitializer().getRValue() and + node2.asExpr() = oi + ) + ) + ) + } + } + /** * User input to static method or constructor call deserialization flow tracking. */ class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration { - TaintToConstructorOrStaticMethodTrackingConfig() { this = "UnsafeDeserialization2" } + TaintToConstructorOrStaticMethodTrackingConfig() { + this = "TaintToConstructorOrStaticMethodTrackingConfig" + } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -826,4 +896,18 @@ module UnsafeDeserialization { ) } } + + /** Newtonsoft.Json.JsonConvert */ + private class NewtonsoftJsonConvertDeserializeObjectMethodSink extends ConstructorOrStaticMethodSink { + NewtonsoftJsonConvertDeserializeObjectMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } + } } diff --git a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll index 48dbe6f70f7..c395840c032 100644 --- a/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll +++ b/csharp/ql/src/semmle/code/csharp/serialization/Deserializers.qll @@ -4,6 +4,7 @@ */ import csharp +import semmle.code.csharp.frameworks.JsonNET::JsonNET /** An unsafe deserializer. */ abstract class UnsafeDeserializer extends Callable { } @@ -67,6 +68,8 @@ class WeakTypeDeserializer extends Class { this instanceof SharpSerializerClass or this instanceof YamlDotNetDeserializerClass + or + this instanceof JsonConvertClass } } @@ -657,3 +660,12 @@ class YamlDotNetDeserializerClasseserializeMethod extends Method, UnsafeDeserial ) } } + +/** `Newtonsoft.Json.JsonConvert.DeserializeObject` method */ +class NewtonsoftJsonConvertClassDeserializeObjectMethod extends Method, UnsafeDeserializer { + NewtonsoftJsonConvertClassDeserializeObjectMethod() { + this.getDeclaringType() instanceof JsonConvertClass and + this.hasName("DeserializeObject") and + this.isStatic() + } +} From 51a614025806756b33b0c9764fd91b3e2405570b Mon Sep 17 00:00:00 2001 From: "${sleep,5}" <52643283+mrthankyou@users.noreply.github.com> Date: Tue, 13 Jul 2021 14:04:06 -0400 Subject: [PATCH 113/429] Change variable name to correct sanitized input variable Co-authored-by: Rasmus Wriedt Larsen --- .../query-tests/Security/CWE-943/mongoengine_good.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py index 1ece6997a89..c9b2b8e762f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/mongoengine_good.py @@ -21,7 +21,7 @@ def connect_find(): safe_search = sanitize(json_search) db = me.connect('mydb') - return db.movie.find({'name': json_search}) + return db.movie.find({'name': safe_search}) # if __name__ == "__main__": # app.run(debug=True) From fd4d8e259529d75cb99bfef7904de3fb12980a2e Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 14 Jul 2021 16:06:34 +0300 Subject: [PATCH 114/429] Use HasFlow instead HasFlowPath --- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index e8ee6bbe058..6fce8c14977 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -50,12 +50,11 @@ where // JsonConvert static method call, but with additional unsafe typename tracking exists( JsonConvertTrackingConfig taintTrackingJsonConvert, TypeNameTrackingConfig typenameTracking, - DataFlow::PathNode settingsCallArg + DataFlow::Node settingsCallArg | taintTrackingJsonConvert.hasFlowPath(userInput, deserializeCallArg) and - typenameTracking.hasFlowPath(_, settingsCallArg) and - deserializeCallArg.getNode().asExpr().getParent() = - settingsCallArg.getNode().asExpr().getParent() + typenameTracking.hasFlow(_, settingsCallArg) and + deserializeCallArg.getNode().asExpr().getParent() = settingsCallArg.asExpr().getParent() ) select deserializeCallArg, userInput, deserializeCallArg, "$@ flows to unsafe deserializer.", userInput, "User-provided data" From 80d784e37ac757175721fe8b2961e63ce7fdff2e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 14 Jul 2021 21:51:36 +0200 Subject: [PATCH 115/429] add a step over empty lookaheads/lookbehinds --- .../security/performance/ReDoSUtil.qll | 47 +++++++++++++++++++ .../performance/SuperlinearBackTracking.qll | 29 ------------ .../ReDoS/PolynomialBackTracking.expected | 4 ++ .../Performance/ReDoS/ReDoS.expected | 2 + .../test/query-tests/Performance/ReDoS/tst.js | 9 +++- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 40b05825bc6..38eede15e8a 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -71,6 +71,49 @@ private int ascii(string char) { ) } +/** + * Holds if `t` matches at least an epsilon symbol. + * + * That is, this term does not restrict the language of the enclosing regular expression. + * + * This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular. + */ +predicate matchesEpsilon(RegExpTerm t) { + t instanceof RegExpStar + or + t instanceof RegExpOpt + or + t.(RegExpRange).getLowerBound() = 0 + or + exists(RegExpTerm child | + child = t.getAChild() and + matchesEpsilon(child) + | + t instanceof RegExpAlt or + t instanceof RegExpGroup or + t instanceof RegExpPlus or + t instanceof RegExpRange + ) + or + matchesEpsilon(t.(RegExpBackRef).getGroup()) + or + forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) +} + +/** + * A lookahead/lookbehind that matches the empty string. + */ +class EmptyPositiveSubPatttern extends RegExpSubPattern { + EmptyPositiveSubPatttern() { + ( + this instanceof RegExpPositiveLookahead + or + this instanceof RegExpPositiveLookbehind + ) and + matchesEpsilon(this.getOperand()) + } +} + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -550,6 +593,10 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { exists(RegExpDollar dollar | q1 = before(dollar) | lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) + or + exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | + lbl = Epsilon() and q2 = after(empty) + ) } /** diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll index 0bbff12b49d..2b42165ff7e 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll @@ -363,35 +363,6 @@ predicate polynimalReDoS(RegExpTerm t, string pump, string prefixMsg, RegExpTerm ) } -/** - * Holds if `t` matches at least an epsilon symbol. - * - * That is, this term does not restrict the language of the enclosing regular expression. - * - * This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular. - */ -private predicate matchesEpsilon(RegExpTerm t) { - t instanceof RegExpStar - or - t instanceof RegExpOpt - or - t.(RegExpRange).getLowerBound() = 0 - or - exists(RegExpTerm child | - child = t.getAChild() and - matchesEpsilon(child) - | - t instanceof RegExpAlt or - t instanceof RegExpGroup or - t instanceof RegExpPlus or - t instanceof RegExpRange - ) - or - matchesEpsilon(t.(RegExpBackRef).getGroup()) - or - forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) -} - /** * Gets a message for why `term` can cause polynomial backtracking. */ diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index ad6bbc49dbb..490373d8b46 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -493,3 +493,7 @@ | 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+)+ | +| tst.js:372:16:372:21 | [^"]*? | Strings starting with '"' and with many repetitions of '""' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+(?=\\s*\|\\s*$)X | +| tst.js:372:24:372:30 | [^"\\s]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+ | +| tst.js:373:16:373:21 | [^"]*? | Strings starting with '"' and with many repetitions of '""' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+(?=X) | +| tst.js:373:24:373:30 | [^"\\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/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 7c7eedf6854..5c57c92108d 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -172,3 +172,5 @@ | tst.js:361:15:361:33 | ((?:a{0\|-)\|\\w\\{\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0'. | | tst.js:362:15:362:35 | ((?:a{0,\|-)\|\\w\\{\\d,)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,'. | | tst.js:363:15:363:38 | ((?:a{0,2\|-)\|\\w\\{\\d,\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,2'. | +| tst.js:372:24:372:30 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | +| tst.js:373:24:373:30 | [^"\\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 6185cdf8add..873ab3b78a0 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -363,4 +363,11 @@ var bad85 = /^((?:a{0,|-)|\w\{\d,)+X$/; var bad86 = /^((?:a{0,2|-)|\w\{\d,\d)+X$/; // GOOD: -var good42 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/; \ No newline at end of file +var good42 = /^((?:a{0,2}|-)|\w\{\d,\d\})+X$/; + +// GOOD +var good43 = /("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)/g; + +// BAD +var bad87 = /("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)X/g; +var bad88 = /("[^"]*?"|[^"\s]+)+(?=X)/g; \ No newline at end of file From de8f64c5be90898ec934080234d52ffe315c9ca2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 14 Jul 2021 21:52:23 +0200 Subject: [PATCH 116/429] sync with python --- .../python/security/performance/ReDoSUtil.qll | 47 +++++++++++++++++++ .../performance/SuperlinearBackTracking.qll | 29 ------------ 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/python/ql/src/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/src/semmle/python/security/performance/ReDoSUtil.qll index 40b05825bc6..38eede15e8a 100644 --- a/python/ql/src/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/src/semmle/python/security/performance/ReDoSUtil.qll @@ -71,6 +71,49 @@ private int ascii(string char) { ) } +/** + * Holds if `t` matches at least an epsilon symbol. + * + * That is, this term does not restrict the language of the enclosing regular expression. + * + * This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular. + */ +predicate matchesEpsilon(RegExpTerm t) { + t instanceof RegExpStar + or + t instanceof RegExpOpt + or + t.(RegExpRange).getLowerBound() = 0 + or + exists(RegExpTerm child | + child = t.getAChild() and + matchesEpsilon(child) + | + t instanceof RegExpAlt or + t instanceof RegExpGroup or + t instanceof RegExpPlus or + t instanceof RegExpRange + ) + or + matchesEpsilon(t.(RegExpBackRef).getGroup()) + or + forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) +} + +/** + * A lookahead/lookbehind that matches the empty string. + */ +class EmptyPositiveSubPatttern extends RegExpSubPattern { + EmptyPositiveSubPatttern() { + ( + this instanceof RegExpPositiveLookahead + or + this instanceof RegExpPositiveLookbehind + ) and + matchesEpsilon(this.getOperand()) + } +} + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -550,6 +593,10 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { exists(RegExpDollar dollar | q1 = before(dollar) | lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) + or + exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | + lbl = Epsilon() and q2 = after(empty) + ) } /** diff --git a/python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll b/python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll index 0bbff12b49d..2b42165ff7e 100644 --- a/python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll +++ b/python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll @@ -363,35 +363,6 @@ predicate polynimalReDoS(RegExpTerm t, string pump, string prefixMsg, RegExpTerm ) } -/** - * Holds if `t` matches at least an epsilon symbol. - * - * That is, this term does not restrict the language of the enclosing regular expression. - * - * This is implemented as an under-approximation, and this predicate does not hold for sub-patterns in particular. - */ -private predicate matchesEpsilon(RegExpTerm t) { - t instanceof RegExpStar - or - t instanceof RegExpOpt - or - t.(RegExpRange).getLowerBound() = 0 - or - exists(RegExpTerm child | - child = t.getAChild() and - matchesEpsilon(child) - | - t instanceof RegExpAlt or - t instanceof RegExpGroup or - t instanceof RegExpPlus or - t instanceof RegExpRange - ) - or - matchesEpsilon(t.(RegExpBackRef).getGroup()) - or - forex(RegExpTerm child | child = t.(RegExpSequence).getAChild() | matchesEpsilon(child)) -} - /** * Gets a message for why `term` can cause polynomial backtracking. */ From 383b5f2ff281e1a1fecda9b2dd5adfd59005cabc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 15 Jul 2021 09:41:53 +0200 Subject: [PATCH 117/429] implement RegExpSubPattern.getOperand in the Python regexp implementation --- python/ql/src/semmle/python/RegexTreeView.qll | 7 +++++++ .../ql/test/query-tests/Security/CWE-730/ReDoS.expected | 2 ++ python/ql/test/query-tests/Security/CWE-730/redos.py | 9 ++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/RegexTreeView.qll b/python/ql/src/semmle/python/RegexTreeView.qll index 5aae3021899..5248f21922f 100644 --- a/python/ql/src/semmle/python/RegexTreeView.qll +++ b/python/ql/src/semmle/python/RegexTreeView.qll @@ -836,6 +836,13 @@ class RegExpZeroWidthMatch extends RegExpGroup { */ class RegExpSubPattern extends RegExpZeroWidthMatch { RegExpSubPattern() { not re.emptyGroup(start, end) } + + /** Gets the lookahead term. */ + RegExpTerm getOperand() { + result.getRegex() = re and + result.getStart() = start + 3 and + result.getEnd() = end - 1 + } } /** diff --git a/python/ql/test/query-tests/Security/CWE-730/ReDoS.expected b/python/ql/test/query-tests/Security/CWE-730/ReDoS.expected index 4a4b5ee4262..21db78dd092 100644 --- a/python/ql/test/query-tests/Security/CWE-730/ReDoS.expected +++ b/python/ql/test/query-tests/Security/CWE-730/ReDoS.expected @@ -93,5 +93,7 @@ | redos.py:364:25:364:45 | ((?:a{0,\|-)\|\\w\\{\\d,)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,'. | | redos.py:365:25:365:48 | ((?:a{0,2\|-)\|\\w\\{\\d,\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,2'. | | redos.py:371:25:371:35 | (\\u0061\|a)* | This part of the regular expression may cause exponential backtracking on strings starting with 'X' and containing many repetitions of 'a'. | +| redos.py:380:35:380:41 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings starting with '/' and containing many repetitions of '!'. | +| redos.py:381:35:381:41 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings starting with '/' and containing many repetitions of '!'. | | unittests.py:5:17:5:23 | (\u00c6\|\\\u00c6)+ | This part of the regular expression may cause exponential backtracking on strings starting with 'X' and containing many repetitions of '\u00c6'. | | unittests.py:9:16:9:24 | (?:.\|\\n)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '\\n'. | diff --git a/python/ql/test/query-tests/Security/CWE-730/redos.py b/python/ql/test/query-tests/Security/CWE-730/redos.py index 37c637c2750..733c594a53a 100644 --- a/python/ql/test/query-tests/Security/CWE-730/redos.py +++ b/python/ql/test/query-tests/Security/CWE-730/redos.py @@ -371,4 +371,11 @@ good42 = re.compile(r'''^((?:a{0,2}|-)|\w\{\d,\d\})+X$''') bad87 = re.compile(r'X(\u0061|a)*Y') # GOOD -good43 = re.compile(r'X(\u0061|b)+Y') \ No newline at end of file +good43 = re.compile(r'X(\u0061|b)+Y') + +# GOOD +good44 = re.compile(r'("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)') + +# BAD +bad88 = re.compile(r'/("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)X') +bad89 = re.compile(r'/("[^"]*?"|[^"\s]+)+(?=X)') \ No newline at end of file From 6f09b95019b2ac2b9980d4fdadb1c0706366d4dd Mon Sep 17 00:00:00 2001 From: jorgectf Date: Thu, 15 Jul 2021 17:16:29 +0200 Subject: [PATCH 118/429] Update `.expected` --- .../Security/CWE-943/NoSQLInjection.expected | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 10c1f852df5..c6dd255a0de 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -10,9 +10,6 @@ edges | flask_mongoengine_good.py:20:21:20:27 | ControlFlowNode for request | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:21:19:21:43 | ControlFlowNode for Attribute() | -| flask_mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | flask_mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -47,21 +44,6 @@ edges | mongoengine_good.py:19:21:19:27 | ControlFlowNode for request | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | -| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | -| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | -| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | @@ -84,10 +66,6 @@ nodes | flask_mongoengine_good.py:20:21:20:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_good.py:20:21:20:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_mongoengine_good.py:21:19:21:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| flask_mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| flask_mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| flask_mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| flask_mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -131,26 +109,6 @@ nodes | mongoengine_good.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_good.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | mongoengine_good.py:20:19:20:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:28:21:28:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:28:21:28:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:28:21:28:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:29:19:29:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:37:21:37:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:37:21:37:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:37:21:37:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:38:19:38:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:45:21:45:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:45:21:45:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:45:21:45:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:46:19:46:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:54:21:54:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:54:21:54:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:54:21:54:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:55:19:55:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | -| mongoengine_good.py:63:21:63:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | -| mongoengine_good.py:63:21:63:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | -| mongoengine_good.py:63:21:63:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | -| mongoengine_good.py:64:19:64:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | From b2b736db104f5b6d4656d6b4809d4f901a6e283f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 16 Jul 2021 13:25:37 +0200 Subject: [PATCH 119/429] add more tests for non-empty positive lookaheads --- .../Performance/ReDoS/PolynomialBackTracking.expected | 4 ++++ .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 4 ++++ javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 490373d8b46..e45cc194d9b 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -497,3 +497,7 @@ | tst.js:372:24:372:30 | [^"\\s]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+ | | tst.js:373:16:373:21 | [^"]*? | Strings starting with '"' and with many repetitions of '""' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+(?=X) | | tst.js:373:24:373:30 | [^"\\s]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+ | +| tst.js:374:15:374:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$) | +| tst.js:375:15:375:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$\|y) | +| tst.js:376:15:376:21 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$) | +| tst.js:377:15:377:21 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$\|y) | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 5c57c92108d..346cf99d0da 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -174,3 +174,7 @@ | tst.js:363:15:363:38 | ((?:a{0,2\|-)\|\\w\\{\\d,\\d)+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a{0,2'. | | tst.js:372:24:372:30 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | tst.js:373:24:373:30 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | +| tst.js:374:15:374:16 | x* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'x'. | +| tst.js:375:15:375:16 | x* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'x'. | +| tst.js:376:15:376:21 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:377:15:377:21 | [\\s\\S]* | 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 873ab3b78a0..8612448014f 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -370,4 +370,8 @@ var good43 = /("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)/g; // BAD var bad87 = /("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)X/g; -var bad88 = /("[^"]*?"|[^"\s]+)+(?=X)/g; \ No newline at end of file +var bad88 = /("[^"]*?"|[^"\s]+)+(?=X)/g; +var bad89 = /(x*)+(?=$)/ +var bad90 = /(x*)+(?=$|y)/ +var bad91 = /([\s\S]*)+(?=$)/ +var bad92 = /([\s\S]*)+(?=$|y)/ \ No newline at end of file From 6da1007f679ad3d2163673c9b48bd765acff1aad Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 16 Jul 2021 13:37:47 +0200 Subject: [PATCH 120/429] mark new redos tests correctly --- .../Performance/ReDoS/PolynomialBackTracking.expected | 4 ++-- .../ql/test/query-tests/Performance/ReDoS/ReDoS.expected | 4 ++-- javascript/ql/test/query-tests/Performance/ReDoS/tst.js | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index e45cc194d9b..03b43ea97be 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -499,5 +499,5 @@ | tst.js:373:24:373:30 | [^"\\s]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ("[^"]*?"\|[^"\\s]+)+ | | tst.js:374:15:374:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$) | | tst.js:375:15:375:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$\|y) | -| tst.js:376:15:376:21 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$) | -| tst.js:377:15:377:21 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$\|y) | +| tst.js:378:16:378:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$) | +| tst.js:379:16:379:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$\|y) | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 346cf99d0da..05352f7a20d 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -176,5 +176,5 @@ | tst.js:373:24:373:30 | [^"\\s]+ | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '!'. | | tst.js:374:15:374:16 | x* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'x'. | | tst.js:375:15:375:16 | x* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'x'. | -| tst.js:376:15:376:21 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | -| tst.js:377:15:377:21 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:378:16:378:22 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:379:16:379:22 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 8612448014f..762929080ae 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -373,5 +373,7 @@ var bad87 = /("[^"]*?"|[^"\s]+)+(?=\s*|\s*$)X/g; var bad88 = /("[^"]*?"|[^"\s]+)+(?=X)/g; var bad89 = /(x*)+(?=$)/ var bad90 = /(x*)+(?=$|y)/ -var bad91 = /([\s\S]*)+(?=$)/ -var bad92 = /([\s\S]*)+(?=$|y)/ \ No newline at end of file + +// GOOD - but we spuriously conclude that a rejecting suffix exists. +var good44 = /([\s\S]*)+(?=$)/; +var good45 = /([\s\S]*)+(?=$|y)/; \ No newline at end of file From 218731ca0aca5c3810bcfd42c9df6655104bc0e3 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Sun, 11 Jul 2021 17:35:26 +0200 Subject: [PATCH 121/429] Added a query for static initialization vectors in encryption - Added StaticInitializationVector.ql - Added StaticInitializationVector.qhelp - Added tests --- .../BadStaticInitializationVector.java | 4 + .../GoodRandomInitializationVector.java | 6 + .../CWE-1204/StaticInitializationVector.qhelp | 46 +++++ .../CWE-1204/StaticInitializationVector.ql | 190 ++++++++++++++++++ .../StaticInitializationVector.expected | 15 ++ .../CWE-1204/StaticInitializationVector.java | 118 +++++++++++ .../CWE-1204/StaticInitializationVector.qlref | 1 + 7 files changed, 380 insertions(+) create mode 100644 java/ql/src/experimental/Security/CWE/CWE-1204/BadStaticInitializationVector.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-1204/GoodRandomInitializationVector.java create mode 100644 java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp create mode 100644 java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql create mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java create mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/BadStaticInitializationVector.java b/java/ql/src/experimental/Security/CWE/CWE-1204/BadStaticInitializationVector.java new file mode 100644 index 00000000000..85e8be6d8ce --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/BadStaticInitializationVector.java @@ -0,0 +1,4 @@ +byte[] iv = new byte[16]; // all zeroes +GCMParameterSpec params = new GCMParameterSpec(128, iv); +Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); +cipher.init(Cipher.ENCRYPT_MODE, key, params); \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/GoodRandomInitializationVector.java b/java/ql/src/experimental/Security/CWE/CWE-1204/GoodRandomInitializationVector.java new file mode 100644 index 00000000000..faceb119d64 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/GoodRandomInitializationVector.java @@ -0,0 +1,6 @@ +byte[] iv = new byte[16]; +SecureRandom random = SecureRandom.getInstanceStrong(); +random.nextBytes(iv); +GCMParameterSpec params = new GCMParameterSpec(128, iv); +Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); +cipher.init(Cipher.ENCRYPT_MODE, key, params); \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp new file mode 100644 index 00000000000..49f5862f3de --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp @@ -0,0 +1,46 @@ + + + + +

    +A cipher needs an initialization vector (IV) when it is used in certain modes +such as CBC or GCM. Under the same secret key, IVs should be unique and ideally unpredictable. +Given a secret key, if the same IV is used for encryption, the same plaintexts result in the same ciphertexts. +This lets an attacker learn if the same data pieces are transfered or stored, +or this can help the attacker run a dictionary attack. +

    +
    + + +

    +Use a random IV generated by SecureRandom. +

    +
    + + +

    +The following example initializes a cipher with a static IV which is unsafe: +

    + + +

    +The next example initializes a cipher with a random IV: +

    + +
    + + +
  • + Wikipedia: + Initialization vector. +
  • +
  • + National Institute of Standards and Technology: + Recommendation for Block Cipher Modes of Operation. +
  • +
  • + National Institute of Standards and Technology: + FIPS 140-2: Security Requirements for Cryptographic Modules. +
  • +
    +
    \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql new file mode 100644 index 00000000000..0d5dcf4ff4d --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql @@ -0,0 +1,190 @@ +/** + * @name Using a static initialization vector for encryption + * @description A cipher needs an initialization vector (IV) in some cases, + * for example, when CBC or GCM modes are used. IVs are used to randomize the encryption, + * therefore they should be unique and ideally unpredictable. + * Otherwise, the same plaintexts result in same ciphertexts under a given secret key. + * If a static IV is used for encryption, this lets an attacker learn + * if the same data pieces are transfered or stored, + * or this can help the attacker run a dictionary attack. + * @kind path-problem + * @problem.severity warning + * @precision high + * @id java/static-initialization-vector + * @tags security + * external/cwe/cwe-329 + * external/cwe/cwe-1204 + */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.TaintTracking2 +import DataFlow::PathGraph + +/** + * Holds if `array` is initialized only with constants, for example, + * `new byte[8]` or `new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }`. + */ +private predicate initializedWithConstants(ArrayCreationExpr array) { + not exists(array.getInit()) + or + forex(Expr element | element = array.getInit().getAChildExpr() | + element instanceof CompileTimeConstantExpr + ) +} + +/** + * An expression that creates a byte array that is initialized with constants. + */ +private class StaticByteArrayCreation extends ArrayCreationExpr { + StaticByteArrayCreation() { + this.getType().(Array).getElementType().(PrimitiveType).getName() = "byte" and + initializedWithConstants(this) + } +} + +/** Defines a sub-set of expressions that update an array. */ +private class ArrayUpdate extends Expr { + Expr array; + + ArrayUpdate() { + exists(Assignment assign, ArrayAccess arrayAccess | arrayAccess = assign.getDest() | + assign = this and + arrayAccess.getArray() = array and + not assign.getSource() instanceof CompileTimeConstantExpr + ) + or + exists(StaticMethodAccess ma | + ma.getMethod().hasQualifiedName("java.lang", "System", "arraycopy") and + ma = this and + ma.getArgument(2) = array + ) + or + exists(StaticMethodAccess ma | + ma.getMethod().hasQualifiedName("java.util", "Arrays", "copyOf") and + ma = this and + ma = array + ) + or + exists(MethodAccess ma, Method m | + m = ma.getMethod() and + ma = this and + ma.getArgument(0) = array + | + m.hasQualifiedName("java.io", "InputStream", "read") or + m.hasQualifiedName("java.nio", "ByteBuffer", "get") or + m.hasQualifiedName("java.security", "SecureRandom", "nextBytes") or + m.hasQualifiedName("java.util", "Random", "nextBytes") + ) + } + + /** Returns the updated array. */ + Expr getArray() { result = array } +} + +/** + * A config that tracks dataflow from creating an array to an operation that updates it. + */ +private class ArrayUpdateConfig extends TaintTracking2::Configuration { + ArrayUpdateConfig() { this = "ArrayUpdateConfig" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof StaticByteArrayCreation + } + + override predicate isSink(DataFlow::Node sink) { + exists(ArrayUpdate update | update.getArray() = sink.asExpr()) + } +} + +/** + * A source that defines an array that doesn't get updated. + */ +private class StaticInitializationVectorSource extends DataFlow::Node { + StaticInitializationVectorSource() { + exists(StaticByteArrayCreation array | array = this.asExpr() | + not exists(ArrayUpdate update, ArrayUpdateConfig config | + config.hasFlow(DataFlow2::exprNode(array), DataFlow2::exprNode(update.getArray())) + ) + ) + } +} + +/** + * A config that tracks initialization of a cipher for encryption. + */ +private class EncryptionModeConfig extends TaintTracking2::Configuration { + EncryptionModeConfig() { this = "EncryptionModeConfig" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(VarAccess).getVariable().hasName("ENCRYPT_MODE") + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, Method m | m = ma.getMethod() | + m.hasQualifiedName("javax.crypto", "Cipher", "init") and + ma.getArgument(0) = sink.asExpr() + ) + } +} + +/** + * A sink that initializes a cipher for encryption with unsafe parameters. + */ +private class EncryptionInitializationSink extends DataFlow::Node { + EncryptionInitializationSink() { + exists(MethodAccess ma, Method m, EncryptionModeConfig config | m = ma.getMethod() | + m.hasQualifiedName("javax.crypto", "Cipher", "init") and + m.getParameterType(2) + .(RefType) + .hasQualifiedName("java.security.spec", "AlgorithmParameterSpec") and + ma.getArgument(2) = this.asExpr() and + config.hasFlowToExpr(ma.getArgument(0)) + ) + } +} + +/** + * Holds if `fromNode` to `toNode` is a dataflow step + * that creates cipher's parameters with initialization vector. + */ +private predicate createInitializationVectorSpecStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + exists(ConstructorCall cc, RefType type | + cc = toNode.asExpr() and type = cc.getConstructedType() + | + type.hasQualifiedName("javax.crypto.spec", "IvParameterSpec") and + cc.getArgument(0) = fromNode.asExpr() + or + type.hasQualifiedName("javax.crypto.spec", ["GCMParameterSpec", "RC2ParameterSpec"]) and + cc.getArgument(1) = fromNode.asExpr() + or + type.hasQualifiedName("javax.crypto.spec", "RC5ParameterSpec") and + cc.getArgument(3) = fromNode.asExpr() + ) +} + +/** + * A config that tracks dataflow to initializing a cipher with a static initialization vector. + */ +private class StaticInitializationVectorConfig extends TaintTracking::Configuration { + StaticInitializationVectorConfig() { this = "StaticInitializationVectorConfig" } + + override predicate isSource(DataFlow::Node source) { + source instanceof StaticInitializationVectorSource + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof EncryptionInitializationSink } + + override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + createInitializationVectorSpecStep(fromNode, toNode) + } + + override predicate isSanitizer(DataFlow::Node node) { + exists(ArrayUpdate update | update.getArray() = node.asExpr()) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, StaticInitializationVectorConfig conf +where conf.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "A $@ should not be used for encryption.", source.getNode(), + "static initialization vector" diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected new file mode 100644 index 00000000000..a26dc0b26ae --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected @@ -0,0 +1,15 @@ +edges +| StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | StaticInitializationVector.java:19:51:19:56 | ivSpec | +| StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | StaticInitializationVector.java:32:51:32:56 | ivSpec | +| StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | StaticInitializationVector.java:48:51:48:56 | ivSpec | +nodes +| StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | +| StaticInitializationVector.java:19:51:19:56 | ivSpec | semmle.label | ivSpec | +| StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | +| StaticInitializationVector.java:32:51:32:56 | ivSpec | semmle.label | ivSpec | +| StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | +| StaticInitializationVector.java:48:51:48:56 | ivSpec | semmle.label | ivSpec | +#select +| StaticInitializationVector.java:19:51:19:56 | ivSpec | StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | StaticInitializationVector.java:19:51:19:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:13:21:13:81 | new byte[] | static initialization vector | +| StaticInitializationVector.java:32:51:32:56 | ivSpec | StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | StaticInitializationVector.java:32:51:32:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:26:21:26:32 | new byte[] | static initialization vector | +| StaticInitializationVector.java:48:51:48:56 | ivSpec | StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | StaticInitializationVector.java:48:51:48:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:39:21:39:32 | new byte[] | static initialization vector | diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java new file mode 100644 index 00000000000..fe02f276bac --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java @@ -0,0 +1,118 @@ +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import java.security.SecureRandom; +import java.util.Arrays; + +public class StaticInitializationVector { + + // BAD: AES-GCM with static IV from a byte array + public byte[] encryptWithStaticIvByteArrayWithInitializer(byte[] key, byte[] plaintext) throws Exception { + byte[] iv = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // BAD: AES-GCM with static IV from zero-initialized byte array + public byte[] encryptWithZeroStaticIvByteArray(byte[] key, byte[] plaintext) throws Exception { + byte[] iv = new byte[16]; + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // BAD: AES-CBC with static IV from zero-initialized byte array + public byte[] encryptWithStaticIvByteArray(byte[] key, byte[] plaintext) throws Exception { + byte[] iv = new byte[16]; + for (byte i = 0; i < iv.length; i++) { + iv[i] = 1; + } + + IvParameterSpec ivSpec = new IvParameterSpec(iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // GOOD: AES-GCM with a random IV + public byte[] encryptWithRandomIv(byte[] key, byte[] plaintext) throws Exception { + byte[] iv = new byte[16]; + + SecureRandom random = SecureRandom.getInstanceStrong(); + random.nextBytes(iv); + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // GOOD: AES-GCM with a random IV + public byte[] encryptWithRandomIvByteByByte(byte[] key, byte[] plaintext) throws Exception { + SecureRandom random = SecureRandom.getInstanceStrong(); + byte[] iv = new byte[16]; + for (int i = 0; i < iv.length; i++) { + iv[i] = (byte) random.nextInt(); + } + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // GOOD: AES-GCM with a random IV + public byte[] encryptWithRandomIvWithSystemArrayCopy(byte[] key, byte[] plaintext) throws Exception { + byte[] randomBytes = new byte[16]; + SecureRandom.getInstanceStrong().nextBytes(randomBytes); + + byte[] iv = new byte[16]; + System.arraycopy(randomBytes, 0, iv, 0, 16); + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } + + // GOOD: AES-GCM with a random IV + public byte[] encryptWithRandomIvWithArraysCopy(byte[] key, byte[] plaintext) throws Exception { + byte[] randomBytes = new byte[16]; + SecureRandom.getInstanceStrong().nextBytes(randomBytes); + + byte[] iv = Arrays.copyOf(randomBytes, 16); + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.update(plaintext); + return cipher.doFinal(); + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref new file mode 100644 index 00000000000..18df4ffb8d3 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref @@ -0,0 +1 @@ +experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql \ No newline at end of file From cfe74b527a9bdbaf9c79e461fe62f3a7b9a5b115 Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Sat, 17 Jul 2021 01:04:52 +0200 Subject: [PATCH 122/429] Use inline-expectation tests for StaticInitializationVector.ql --- .../CWE-1204/StaticInitializationVector.ql | 166 +----------------- .../StaticInitializationVectorQuery.qll | 166 ++++++++++++++++++ .../StaticInitializationVector.expected | 15 -- .../CWE-1204/StaticInitializationVector.java | 6 +- .../CWE-1204/StaticInitializationVector.qlref | 1 - .../StaticInitializationVectorTest.expected | 0 .../StaticInitializationVectorTest.ql | 20 +++ 7 files changed, 190 insertions(+), 184 deletions(-) create mode 100644 java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected delete mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref create mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.expected create mode 100644 java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql index 0d5dcf4ff4d..f041919ed93 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql @@ -17,173 +17,9 @@ */ import java -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.dataflow.TaintTracking2 +import experimental.semmle.code.java.security.StaticInitializationVectorQuery import DataFlow::PathGraph -/** - * Holds if `array` is initialized only with constants, for example, - * `new byte[8]` or `new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }`. - */ -private predicate initializedWithConstants(ArrayCreationExpr array) { - not exists(array.getInit()) - or - forex(Expr element | element = array.getInit().getAChildExpr() | - element instanceof CompileTimeConstantExpr - ) -} - -/** - * An expression that creates a byte array that is initialized with constants. - */ -private class StaticByteArrayCreation extends ArrayCreationExpr { - StaticByteArrayCreation() { - this.getType().(Array).getElementType().(PrimitiveType).getName() = "byte" and - initializedWithConstants(this) - } -} - -/** Defines a sub-set of expressions that update an array. */ -private class ArrayUpdate extends Expr { - Expr array; - - ArrayUpdate() { - exists(Assignment assign, ArrayAccess arrayAccess | arrayAccess = assign.getDest() | - assign = this and - arrayAccess.getArray() = array and - not assign.getSource() instanceof CompileTimeConstantExpr - ) - or - exists(StaticMethodAccess ma | - ma.getMethod().hasQualifiedName("java.lang", "System", "arraycopy") and - ma = this and - ma.getArgument(2) = array - ) - or - exists(StaticMethodAccess ma | - ma.getMethod().hasQualifiedName("java.util", "Arrays", "copyOf") and - ma = this and - ma = array - ) - or - exists(MethodAccess ma, Method m | - m = ma.getMethod() and - ma = this and - ma.getArgument(0) = array - | - m.hasQualifiedName("java.io", "InputStream", "read") or - m.hasQualifiedName("java.nio", "ByteBuffer", "get") or - m.hasQualifiedName("java.security", "SecureRandom", "nextBytes") or - m.hasQualifiedName("java.util", "Random", "nextBytes") - ) - } - - /** Returns the updated array. */ - Expr getArray() { result = array } -} - -/** - * A config that tracks dataflow from creating an array to an operation that updates it. - */ -private class ArrayUpdateConfig extends TaintTracking2::Configuration { - ArrayUpdateConfig() { this = "ArrayUpdateConfig" } - - override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof StaticByteArrayCreation - } - - override predicate isSink(DataFlow::Node sink) { - exists(ArrayUpdate update | update.getArray() = sink.asExpr()) - } -} - -/** - * A source that defines an array that doesn't get updated. - */ -private class StaticInitializationVectorSource extends DataFlow::Node { - StaticInitializationVectorSource() { - exists(StaticByteArrayCreation array | array = this.asExpr() | - not exists(ArrayUpdate update, ArrayUpdateConfig config | - config.hasFlow(DataFlow2::exprNode(array), DataFlow2::exprNode(update.getArray())) - ) - ) - } -} - -/** - * A config that tracks initialization of a cipher for encryption. - */ -private class EncryptionModeConfig extends TaintTracking2::Configuration { - EncryptionModeConfig() { this = "EncryptionModeConfig" } - - override predicate isSource(DataFlow::Node source) { - source.asExpr().(VarAccess).getVariable().hasName("ENCRYPT_MODE") - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess ma, Method m | m = ma.getMethod() | - m.hasQualifiedName("javax.crypto", "Cipher", "init") and - ma.getArgument(0) = sink.asExpr() - ) - } -} - -/** - * A sink that initializes a cipher for encryption with unsafe parameters. - */ -private class EncryptionInitializationSink extends DataFlow::Node { - EncryptionInitializationSink() { - exists(MethodAccess ma, Method m, EncryptionModeConfig config | m = ma.getMethod() | - m.hasQualifiedName("javax.crypto", "Cipher", "init") and - m.getParameterType(2) - .(RefType) - .hasQualifiedName("java.security.spec", "AlgorithmParameterSpec") and - ma.getArgument(2) = this.asExpr() and - config.hasFlowToExpr(ma.getArgument(0)) - ) - } -} - -/** - * Holds if `fromNode` to `toNode` is a dataflow step - * that creates cipher's parameters with initialization vector. - */ -private predicate createInitializationVectorSpecStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - exists(ConstructorCall cc, RefType type | - cc = toNode.asExpr() and type = cc.getConstructedType() - | - type.hasQualifiedName("javax.crypto.spec", "IvParameterSpec") and - cc.getArgument(0) = fromNode.asExpr() - or - type.hasQualifiedName("javax.crypto.spec", ["GCMParameterSpec", "RC2ParameterSpec"]) and - cc.getArgument(1) = fromNode.asExpr() - or - type.hasQualifiedName("javax.crypto.spec", "RC5ParameterSpec") and - cc.getArgument(3) = fromNode.asExpr() - ) -} - -/** - * A config that tracks dataflow to initializing a cipher with a static initialization vector. - */ -private class StaticInitializationVectorConfig extends TaintTracking::Configuration { - StaticInitializationVectorConfig() { this = "StaticInitializationVectorConfig" } - - override predicate isSource(DataFlow::Node source) { - source instanceof StaticInitializationVectorSource - } - - override predicate isSink(DataFlow::Node sink) { sink instanceof EncryptionInitializationSink } - - override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - createInitializationVectorSpecStep(fromNode, toNode) - } - - override predicate isSanitizer(DataFlow::Node node) { - exists(ArrayUpdate update | update.getArray() = node.asExpr()) - } -} - from DataFlow::PathNode source, DataFlow::PathNode sink, StaticInitializationVectorConfig conf where conf.hasFlowPath(source, sink) select sink.getNode(), source, sink, "A $@ should not be used for encryption.", source.getNode(), diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll new file mode 100644 index 00000000000..f190153385e --- /dev/null +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -0,0 +1,166 @@ +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.TaintTracking2 + +/** + * Holds if `array` is initialized only with constants, for example, + * `new byte[8]` or `new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }`. + */ +private predicate initializedWithConstants(ArrayCreationExpr array) { + not exists(array.getInit()) + or + forex(Expr element | element = array.getInit().getAChildExpr() | + element instanceof CompileTimeConstantExpr + ) +} + +/** + * An expression that creates a byte array that is initialized with constants. + */ +private class StaticByteArrayCreation extends ArrayCreationExpr { + StaticByteArrayCreation() { + this.getType().(Array).getElementType().(PrimitiveType).getName() = "byte" and + initializedWithConstants(this) + } +} + +/** Defines a sub-set of expressions that update an array. */ +private class ArrayUpdate extends Expr { + Expr array; + + ArrayUpdate() { + exists(Assignment assign, ArrayAccess arrayAccess | arrayAccess = assign.getDest() | + assign = this and + arrayAccess.getArray() = array and + not assign.getSource() instanceof CompileTimeConstantExpr + ) + or + exists(StaticMethodAccess ma | + ma.getMethod().hasQualifiedName("java.lang", "System", "arraycopy") and + ma = this and + ma.getArgument(2) = array + ) + or + exists(StaticMethodAccess ma | + ma.getMethod().hasQualifiedName("java.util", "Arrays", "copyOf") and + ma = this and + ma = array + ) + or + exists(MethodAccess ma, Method m | + m = ma.getMethod() and + ma = this and + ma.getArgument(0) = array + | + m.hasQualifiedName("java.io", "InputStream", "read") or + m.hasQualifiedName("java.nio", "ByteBuffer", "get") or + m.hasQualifiedName("java.security", "SecureRandom", "nextBytes") or + m.hasQualifiedName("java.util", "Random", "nextBytes") + ) + } + + /** Returns the updated array. */ + Expr getArray() { result = array } +} + +/** + * A config that tracks dataflow from creating an array to an operation that updates it. + */ +private class ArrayUpdateConfig extends TaintTracking2::Configuration { + ArrayUpdateConfig() { this = "ArrayUpdateConfig" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof StaticByteArrayCreation + } + + override predicate isSink(DataFlow::Node sink) { + exists(ArrayUpdate update | update.getArray() = sink.asExpr()) + } +} + +/** + * A source that defines an array that doesn't get updated. + */ +private class StaticInitializationVectorSource extends DataFlow::Node { + StaticInitializationVectorSource() { + exists(StaticByteArrayCreation array | array = this.asExpr() | + not exists(ArrayUpdate update, ArrayUpdateConfig config | + config.hasFlow(DataFlow2::exprNode(array), DataFlow2::exprNode(update.getArray())) + ) + ) + } +} + +/** + * A config that tracks initialization of a cipher for encryption. + */ +private class EncryptionModeConfig extends TaintTracking2::Configuration { + EncryptionModeConfig() { this = "EncryptionModeConfig" } + + override predicate isSource(DataFlow::Node source) { + source.asExpr().(VarAccess).getVariable().hasName("ENCRYPT_MODE") + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, Method m | m = ma.getMethod() | + m.hasQualifiedName("javax.crypto", "Cipher", "init") and + ma.getArgument(0) = sink.asExpr() + ) + } +} + +/** + * A sink that initializes a cipher for encryption with unsafe parameters. + */ +private class EncryptionInitializationSink extends DataFlow::Node { + EncryptionInitializationSink() { + exists(MethodAccess ma, Method m, EncryptionModeConfig config | m = ma.getMethod() | + m.hasQualifiedName("javax.crypto", "Cipher", "init") and + m.getParameterType(2) + .(RefType) + .hasQualifiedName("java.security.spec", "AlgorithmParameterSpec") and + ma.getArgument(2) = this.asExpr() and + config.hasFlowToExpr(ma.getArgument(0)) + ) + } +} + +/** + * Holds if `fromNode` to `toNode` is a dataflow step + * that creates cipher's parameters with initialization vector. + */ +private predicate createInitializationVectorSpecStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + exists(ConstructorCall cc, RefType type | + cc = toNode.asExpr() and type = cc.getConstructedType() + | + type.hasQualifiedName("javax.crypto.spec", "IvParameterSpec") and + cc.getArgument(0) = fromNode.asExpr() + or + type.hasQualifiedName("javax.crypto.spec", ["GCMParameterSpec", "RC2ParameterSpec"]) and + cc.getArgument(1) = fromNode.asExpr() + or + type.hasQualifiedName("javax.crypto.spec", "RC5ParameterSpec") and + cc.getArgument(3) = fromNode.asExpr() + ) +} + +/** + * A config that tracks dataflow to initializing a cipher with a static initialization vector. + */ +class StaticInitializationVectorConfig extends TaintTracking::Configuration { + StaticInitializationVectorConfig() { this = "StaticInitializationVectorConfig" } + + override predicate isSource(DataFlow::Node source) { + source instanceof StaticInitializationVectorSource + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof EncryptionInitializationSink } + + override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + createInitializationVectorSpecStep(fromNode, toNode) + } + + override predicate isSanitizer(DataFlow::Node node) { + exists(ArrayUpdate update | update.getArray() = node.asExpr()) + } +} diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected deleted file mode 100644 index a26dc0b26ae..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.expected +++ /dev/null @@ -1,15 +0,0 @@ -edges -| StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | StaticInitializationVector.java:19:51:19:56 | ivSpec | -| StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | StaticInitializationVector.java:32:51:32:56 | ivSpec | -| StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | StaticInitializationVector.java:48:51:48:56 | ivSpec | -nodes -| StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | -| StaticInitializationVector.java:19:51:19:56 | ivSpec | semmle.label | ivSpec | -| StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | -| StaticInitializationVector.java:32:51:32:56 | ivSpec | semmle.label | ivSpec | -| StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | semmle.label | new byte[] : byte[] | -| StaticInitializationVector.java:48:51:48:56 | ivSpec | semmle.label | ivSpec | -#select -| StaticInitializationVector.java:19:51:19:56 | ivSpec | StaticInitializationVector.java:13:21:13:81 | new byte[] : byte[] | StaticInitializationVector.java:19:51:19:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:13:21:13:81 | new byte[] | static initialization vector | -| StaticInitializationVector.java:32:51:32:56 | ivSpec | StaticInitializationVector.java:26:21:26:32 | new byte[] : byte[] | StaticInitializationVector.java:32:51:32:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:26:21:26:32 | new byte[] | static initialization vector | -| StaticInitializationVector.java:48:51:48:56 | ivSpec | StaticInitializationVector.java:39:21:39:32 | new byte[] : byte[] | StaticInitializationVector.java:48:51:48:56 | ivSpec | A $@ should not be used for encryption. | StaticInitializationVector.java:39:21:39:32 | new byte[] | static initialization vector | diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java index fe02f276bac..95a0d4b49f8 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java @@ -16,7 +16,7 @@ public class StaticInitializationVector { SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector cipher.update(plaintext); return cipher.doFinal(); } @@ -29,7 +29,7 @@ public class StaticInitializationVector { SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector cipher.update(plaintext); return cipher.doFinal(); } @@ -45,7 +45,7 @@ public class StaticInitializationVector { SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector cipher.update(plaintext); return cipher.doFinal(); } diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref deleted file mode 100644 index 18df4ffb8d3..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql \ No newline at end of file diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.expected b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql new file mode 100644 index 00000000000..29afc31ab04 --- /dev/null +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql @@ -0,0 +1,20 @@ +import java +import experimental.semmle.code.java.security.StaticInitializationVectorQuery +import TestUtilities.InlineExpectationsTest + +class StaticInitializationVectorTest extends InlineExpectationsTest { + StaticInitializationVectorTest() { this = "StaticInitializationVectorTest" } + + override string getARelevantTag() { result = "staticInitializationVector" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "staticInitializationVector" and + exists(DataFlow::Node src, DataFlow::Node sink, StaticInitializationVectorConfig conf | + conf.hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} From 69dab4907304743efe4e9208541a3da17318c117 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Mon, 19 Jul 2021 12:24:05 +0100 Subject: [PATCH 123/429] Docs: Running query on multiple DBs in CodeQL for VS Code --- .../analyzing-your-projects.rst | 9 +++++++++ 1 file changed, 9 insertions(+) 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 b9a275cfb41..cfd1746499c 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 @@ -97,6 +97,15 @@ For example, in the following snippet, you could select the predicate name ``foo predicate foo(string s) { s = "bar" } +Running a query on multiple databases +-------------------------------------- + +This is helpful if you want to test your query on multiple codebases, or find a vulnerability in multiple projects. + +#. Open a query (``.ql``) file. +#. Right-click and select **CodeQL: Run Query on Multiple Databases**. +#. From the dropdown menu, select the databases that you want to run the query on. + Viewing previous queries -------------------------- From 7939a1372e3068a19a5563f6f36400013806be5e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 19 Jul 2021 16:44:41 +0200 Subject: [PATCH 124/429] Python: Move Jinja2WithoutEscaping tests to own folder --- .../Jinja2WithoutEscaping.expected | 0 .../Jinja2WithoutEscaping.qlref | 0 .../{CWE-079 => CWE-079-Jinja2WithoutEscaping}/jinja2_escaping.py | 0 .../Security/{CWE-079 => CWE-079-Jinja2WithoutEscaping}/options | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-Jinja2WithoutEscaping}/Jinja2WithoutEscaping.expected (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-Jinja2WithoutEscaping}/Jinja2WithoutEscaping.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-Jinja2WithoutEscaping}/jinja2_escaping.py (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-Jinja2WithoutEscaping}/options (100%) diff --git a/python/ql/test/query-tests/Security/CWE-079/Jinja2WithoutEscaping.expected b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/Jinja2WithoutEscaping.expected rename to python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.expected diff --git a/python/ql/test/query-tests/Security/CWE-079/Jinja2WithoutEscaping.qlref b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/Jinja2WithoutEscaping.qlref rename to python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/Jinja2WithoutEscaping.qlref diff --git a/python/ql/test/query-tests/Security/CWE-079/jinja2_escaping.py b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/jinja2_escaping.py rename to python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/jinja2_escaping.py diff --git a/python/ql/test/query-tests/Security/CWE-079/options b/python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/options rename to python/ql/test/query-tests/Security/CWE-079-Jinja2WithoutEscaping/options From da021feb8b014574f8f7f4e6dcf9b651c82b8fda Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 19 Jul 2021 16:48:21 +0200 Subject: [PATCH 125/429] Python: Move `py/incomplete-hostname-regexp` tests to own folder --- .../IncompleteHostnameRegExp.expected | 0 .../IncompleteHostnameRegExp.qlref | 0 .../{CWE-020 => CWE-020-IncompleteHostnameRegExp}/hosttest.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteHostnameRegExp}/IncompleteHostnameRegExp.expected (100%) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteHostnameRegExp}/IncompleteHostnameRegExp.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteHostnameRegExp}/hosttest.py (100%) diff --git a/python/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.expected b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.expected rename to python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.expected diff --git a/python/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.qlref b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegExp.qlref rename to python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/IncompleteHostnameRegExp.qlref diff --git a/python/ql/test/query-tests/Security/CWE-020/hosttest.py b/python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/hosttest.py rename to python/ql/test/query-tests/Security/CWE-020-IncompleteHostnameRegExp/hosttest.py From 77021ae1193be29d73667940c613234790cdd6f8 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 19 Jul 2021 16:54:34 +0200 Subject: [PATCH 126/429] Python: Restructure security tests to contain query name We were mixing between things, so this is just to keep things consistent. Even though it's not strictly needed for all queries, it does look nice I think --- .../IncompleteUrlSubstringSanitization.expected | 0 .../IncompleteUrlSubstringSanitization.qlref | 0 .../urltest.py | 0 .../CommandInjection.expected | 0 .../CommandInjection.qlref | 0 .../command_injection.py | 0 .../{CWE-078-py2 => CWE-078-CommandInjection-py2}/options | 0 .../CommandInjection.expected | 0 .../{CWE-078 => CWE-078-CommandInjection}/CommandInjection.qlref | 0 .../{CWE-078 => CWE-078-CommandInjection}/command_injection.py | 0 .../Security/{CWE-078 => CWE-078-CommandInjection}/options | 0 .../{CWE-079 => CWE-079-ReflectedXss}/ReflectedXss.expected | 0 .../Security/{CWE-079 => CWE-079-ReflectedXss}/ReflectedXss.qlref | 0 .../Security/{CWE-079 => CWE-079-ReflectedXss}/reflected_xss.py | 0 .../{CWE-089 => CWE-089-SqlInjection}/SqlInjection.expected | 0 .../Security/{CWE-089 => CWE-089-SqlInjection}/SqlInjection.qlref | 0 .../Security/{CWE-089 => CWE-089-SqlInjection}/sql_injection.py | 0 .../{CWE-094 => CWE-094-CodeInjection}/CodeInjection.expected | 0 .../{CWE-094 => CWE-094-CodeInjection}/CodeInjection.qlref | 0 .../Security/{CWE-094 => CWE-094-CodeInjection}/code_injection.py | 0 .../ExceptionInfo.expected | 0 .../{CWE-209 => CWE-209-StackTraceExposure}/ExceptionInfo.ql | 0 .../{CWE-209 => CWE-209-StackTraceExposure}/Exceptions.py | 0 .../StackTraceExposure.expected | 0 .../StackTraceExposure.qlref | 0 .../{CWE-209 => CWE-209-StackTraceExposure}/Stacktrace.py | 0 .../Security/{CWE-209 => CWE-209-StackTraceExposure}/options | 0 .../Security/{CWE-209 => CWE-209-StackTraceExposure}/test.py | 0 .../Security/{CWE-215 => CWE-215-FlaskDebug}/FlaskDebug.expected | 0 .../Security/{CWE-215 => CWE-215-FlaskDebug}/FlaskDebug.qlref | 0 .../query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/options | 0 .../Security/{CWE-215 => CWE-215-FlaskDebug}/settings.py | 0 .../query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/test.py | 0 .../{CWE-326 => CWE-326-WeakCryptoKey}/WeakCryptoKey.expected | 0 .../{CWE-326 => CWE-326-WeakCryptoKey}/WeakCryptoKey.qlref | 0 .../Security/{CWE-326 => CWE-326-WeakCryptoKey}/test_example.py | 0 .../Security/{CWE-326 => CWE-326-WeakCryptoKey}/weak_crypto.py | 0 .../InsecureTemporaryFile.expected | 0 .../InsecureTemporaryFile.py | 0 .../InsecureTemporaryFile.qlref | 0 .../SecureTemporaryFile.py | 0 .../UnsafeDeserialization.expected | 0 .../UnsafeDeserialization.qlref | 0 .../unsafe_deserialization.py | 0 .../{CWE-601 => CWE-601-UrlRedirect}/UrlRedirect.expected | 0 .../Security/{CWE-601 => CWE-601-UrlRedirect}/UrlRedirect.qlref | 0 .../query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/options | 0 .../query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/test.py | 0 .../WeakFilePermissions.expected | 0 .../WeakFilePermissions.qlref | 0 .../Security/{CWE-732 => CWE-732-WeakFilePermissions}/options | 0 .../Security/{CWE-732 => CWE-732-WeakFilePermissions}/test.py | 0 .../HardcodedCredentials.expected | 0 .../HardcodedCredentials.qlref | 0 .../Security/{CWE-798 => CWE-798-HardcodedCredentials}/test.py | 0 55 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteUrlSubstringSanitization}/IncompleteUrlSubstringSanitization.expected (100%) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteUrlSubstringSanitization}/IncompleteUrlSubstringSanitization.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-020 => CWE-020-IncompleteUrlSubstringSanitization}/urltest.py (100%) rename python/ql/test/query-tests/Security/{CWE-078-py2 => CWE-078-CommandInjection-py2}/CommandInjection.expected (100%) rename python/ql/test/query-tests/Security/{CWE-078-py2 => CWE-078-CommandInjection-py2}/CommandInjection.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-078-py2 => CWE-078-CommandInjection-py2}/command_injection.py (100%) rename python/ql/test/query-tests/Security/{CWE-078-py2 => CWE-078-CommandInjection-py2}/options (100%) rename python/ql/test/query-tests/Security/{CWE-078 => CWE-078-CommandInjection}/CommandInjection.expected (100%) rename python/ql/test/query-tests/Security/{CWE-078 => CWE-078-CommandInjection}/CommandInjection.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-078 => CWE-078-CommandInjection}/command_injection.py (100%) rename python/ql/test/query-tests/Security/{CWE-078 => CWE-078-CommandInjection}/options (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-ReflectedXss}/ReflectedXss.expected (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-ReflectedXss}/ReflectedXss.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-079 => CWE-079-ReflectedXss}/reflected_xss.py (100%) rename python/ql/test/query-tests/Security/{CWE-089 => CWE-089-SqlInjection}/SqlInjection.expected (100%) rename python/ql/test/query-tests/Security/{CWE-089 => CWE-089-SqlInjection}/SqlInjection.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-089 => CWE-089-SqlInjection}/sql_injection.py (100%) rename python/ql/test/query-tests/Security/{CWE-094 => CWE-094-CodeInjection}/CodeInjection.expected (100%) rename python/ql/test/query-tests/Security/{CWE-094 => CWE-094-CodeInjection}/CodeInjection.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-094 => CWE-094-CodeInjection}/code_injection.py (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/ExceptionInfo.expected (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/ExceptionInfo.ql (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/Exceptions.py (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/StackTraceExposure.expected (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/StackTraceExposure.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/Stacktrace.py (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/options (100%) rename python/ql/test/query-tests/Security/{CWE-209 => CWE-209-StackTraceExposure}/test.py (100%) rename python/ql/test/query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/FlaskDebug.expected (100%) rename python/ql/test/query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/FlaskDebug.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/options (100%) rename python/ql/test/query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/settings.py (100%) rename python/ql/test/query-tests/Security/{CWE-215 => CWE-215-FlaskDebug}/test.py (100%) rename python/ql/test/query-tests/Security/{CWE-326 => CWE-326-WeakCryptoKey}/WeakCryptoKey.expected (100%) rename python/ql/test/query-tests/Security/{CWE-326 => CWE-326-WeakCryptoKey}/WeakCryptoKey.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-326 => CWE-326-WeakCryptoKey}/test_example.py (100%) rename python/ql/test/query-tests/Security/{CWE-326 => CWE-326-WeakCryptoKey}/weak_crypto.py (100%) rename python/ql/test/query-tests/Security/{CWE-377 => CWE-377-InsecureTemporaryFile}/InsecureTemporaryFile.expected (100%) rename python/ql/test/query-tests/Security/{CWE-377 => CWE-377-InsecureTemporaryFile}/InsecureTemporaryFile.py (100%) rename python/ql/test/query-tests/Security/{CWE-377 => CWE-377-InsecureTemporaryFile}/InsecureTemporaryFile.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-377 => CWE-377-InsecureTemporaryFile}/SecureTemporaryFile.py (100%) rename python/ql/test/query-tests/Security/{CWE-502 => CWE-502-UnsafeDeserialization}/UnsafeDeserialization.expected (100%) rename python/ql/test/query-tests/Security/{CWE-502 => CWE-502-UnsafeDeserialization}/UnsafeDeserialization.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-502 => CWE-502-UnsafeDeserialization}/unsafe_deserialization.py (100%) rename python/ql/test/query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/UrlRedirect.expected (100%) rename python/ql/test/query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/UrlRedirect.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/options (100%) rename python/ql/test/query-tests/Security/{CWE-601 => CWE-601-UrlRedirect}/test.py (100%) rename python/ql/test/query-tests/Security/{CWE-732 => CWE-732-WeakFilePermissions}/WeakFilePermissions.expected (100%) rename python/ql/test/query-tests/Security/{CWE-732 => CWE-732-WeakFilePermissions}/WeakFilePermissions.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-732 => CWE-732-WeakFilePermissions}/options (100%) rename python/ql/test/query-tests/Security/{CWE-732 => CWE-732-WeakFilePermissions}/test.py (100%) rename python/ql/test/query-tests/Security/{CWE-798 => CWE-798-HardcodedCredentials}/HardcodedCredentials.expected (100%) rename python/ql/test/query-tests/Security/{CWE-798 => CWE-798-HardcodedCredentials}/HardcodedCredentials.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-798 => CWE-798-HardcodedCredentials}/test.py (100%) diff --git a/python/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected rename to python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected diff --git a/python/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.qlref b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.qlref rename to python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.qlref diff --git a/python/ql/test/query-tests/Security/CWE-020/urltest.py b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-020/urltest.py rename to python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/urltest.py diff --git a/python/ql/test/query-tests/Security/CWE-078-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078-py2/CommandInjection.expected rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected diff --git a/python/ql/test/query-tests/Security/CWE-078-py2/CommandInjection.qlref b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078-py2/CommandInjection.qlref rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.qlref diff --git a/python/ql/test/query-tests/Security/CWE-078-py2/command_injection.py b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078-py2/command_injection.py rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/command_injection.py diff --git a/python/ql/test/query-tests/Security/CWE-078-py2/options b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078-py2/options rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/options diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078/CommandInjection.qlref rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.qlref diff --git a/python/ql/test/query-tests/Security/CWE-078/command_injection.py b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078/command_injection.py rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py diff --git a/python/ql/test/query-tests/Security/CWE-078/options b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-078/options rename to python/ql/test/query-tests/Security/CWE-078-CommandInjection/options diff --git a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected rename to python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected diff --git a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.qlref b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/ReflectedXss.qlref rename to python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.qlref diff --git a/python/ql/test/query-tests/Security/CWE-079/reflected_xss.py b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-079/reflected_xss.py rename to python/ql/test/query-tests/Security/CWE-079-ReflectedXss/reflected_xss.py diff --git a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected rename to python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected diff --git a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-089/SqlInjection.qlref rename to python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.qlref diff --git a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-089/sql_injection.py rename to python/ql/test/query-tests/Security/CWE-089-SqlInjection/sql_injection.py diff --git a/python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected rename to python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected diff --git a/python/ql/test/query-tests/Security/CWE-094/CodeInjection.qlref b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-094/CodeInjection.qlref rename to python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.qlref diff --git a/python/ql/test/query-tests/Security/CWE-094/code_injection.py b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/code_injection.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-094/code_injection.py rename to python/ql/test/query-tests/Security/CWE-094-CodeInjection/code_injection.py diff --git a/python/ql/test/query-tests/Security/CWE-209/ExceptionInfo.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/ExceptionInfo.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/ExceptionInfo.expected rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/ExceptionInfo.expected diff --git a/python/ql/test/query-tests/Security/CWE-209/ExceptionInfo.ql b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/ExceptionInfo.ql similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/ExceptionInfo.ql rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/ExceptionInfo.ql diff --git a/python/ql/test/query-tests/Security/CWE-209/Exceptions.py b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/Exceptions.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/Exceptions.py rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/Exceptions.py diff --git a/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected diff --git a/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.qlref rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.qlref diff --git a/python/ql/test/query-tests/Security/CWE-209/Stacktrace.py b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/Stacktrace.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/Stacktrace.py rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/Stacktrace.py diff --git a/python/ql/test/query-tests/Security/CWE-209/options b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/options rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/options diff --git a/python/ql/test/query-tests/Security/CWE-209/test.py b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-209/test.py rename to python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/test.py diff --git a/python/ql/test/query-tests/Security/CWE-215/FlaskDebug.expected b/python/ql/test/query-tests/Security/CWE-215-FlaskDebug/FlaskDebug.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-215/FlaskDebug.expected rename to python/ql/test/query-tests/Security/CWE-215-FlaskDebug/FlaskDebug.expected diff --git a/python/ql/test/query-tests/Security/CWE-215/FlaskDebug.qlref b/python/ql/test/query-tests/Security/CWE-215-FlaskDebug/FlaskDebug.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-215/FlaskDebug.qlref rename to python/ql/test/query-tests/Security/CWE-215-FlaskDebug/FlaskDebug.qlref diff --git a/python/ql/test/query-tests/Security/CWE-215/options b/python/ql/test/query-tests/Security/CWE-215-FlaskDebug/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-215/options rename to python/ql/test/query-tests/Security/CWE-215-FlaskDebug/options diff --git a/python/ql/test/query-tests/Security/CWE-215/settings.py b/python/ql/test/query-tests/Security/CWE-215-FlaskDebug/settings.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-215/settings.py rename to python/ql/test/query-tests/Security/CWE-215-FlaskDebug/settings.py diff --git a/python/ql/test/query-tests/Security/CWE-215/test.py b/python/ql/test/query-tests/Security/CWE-215-FlaskDebug/test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-215/test.py rename to python/ql/test/query-tests/Security/CWE-215-FlaskDebug/test.py diff --git a/python/ql/test/query-tests/Security/CWE-326/WeakCryptoKey.expected b/python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/WeakCryptoKey.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-326/WeakCryptoKey.expected rename to python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/WeakCryptoKey.expected diff --git a/python/ql/test/query-tests/Security/CWE-326/WeakCryptoKey.qlref b/python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/WeakCryptoKey.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-326/WeakCryptoKey.qlref rename to python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/WeakCryptoKey.qlref diff --git a/python/ql/test/query-tests/Security/CWE-326/test_example.py b/python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/test_example.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-326/test_example.py rename to python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/test_example.py diff --git a/python/ql/test/query-tests/Security/CWE-326/weak_crypto.py b/python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/weak_crypto.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-326/weak_crypto.py rename to python/ql/test/query-tests/Security/CWE-326-WeakCryptoKey/weak_crypto.py diff --git a/python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.expected b/python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.expected rename to python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.expected diff --git a/python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.py b/python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.py rename to python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.py diff --git a/python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.qlref b/python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-377/InsecureTemporaryFile.qlref rename to python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/InsecureTemporaryFile.qlref diff --git a/python/ql/test/query-tests/Security/CWE-377/SecureTemporaryFile.py b/python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/SecureTemporaryFile.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-377/SecureTemporaryFile.py rename to python/ql/test/query-tests/Security/CWE-377-InsecureTemporaryFile/SecureTemporaryFile.py diff --git a/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected rename to python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected diff --git a/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.qlref b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.qlref rename to python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.qlref diff --git a/python/ql/test/query-tests/Security/CWE-502/unsafe_deserialization.py b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/unsafe_deserialization.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-502/unsafe_deserialization.py rename to python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/unsafe_deserialization.py diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected rename to python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.qlref b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-601/UrlRedirect.qlref rename to python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.qlref diff --git a/python/ql/test/query-tests/Security/CWE-601/options b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-601/options rename to python/ql/test/query-tests/Security/CWE-601-UrlRedirect/options diff --git a/python/ql/test/query-tests/Security/CWE-601/test.py b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-601/test.py rename to python/ql/test/query-tests/Security/CWE-601-UrlRedirect/test.py diff --git a/python/ql/test/query-tests/Security/CWE-732/WeakFilePermissions.expected b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-732/WeakFilePermissions.expected rename to python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.expected diff --git a/python/ql/test/query-tests/Security/CWE-732/WeakFilePermissions.qlref b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-732/WeakFilePermissions.qlref rename to python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/WeakFilePermissions.qlref diff --git a/python/ql/test/query-tests/Security/CWE-732/options b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-732/options rename to python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/options diff --git a/python/ql/test/query-tests/Security/CWE-732/test.py b/python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-732/test.py rename to python/ql/test/query-tests/Security/CWE-732-WeakFilePermissions/test.py diff --git a/python/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected rename to python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected diff --git a/python/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.qlref b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.qlref rename to python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.qlref diff --git a/python/ql/test/query-tests/Security/CWE-798/test.py b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-798/test.py rename to python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test.py From 5939128a76d137d292752ddf18528b7c182d73e7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 19 Jul 2021 16:56:07 +0200 Subject: [PATCH 127/429] Python: Fix test folder for InsecureDefaultProtocol it was named wrong before. whoops. --- .../InsecureDefaultProtocol.expected | 0 .../InsecureDefaultProtocol.qlref | 0 .../InsecureProtocol.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-327-InsecureProtocol => CWE-327-InsecureDefaultProtocol}/InsecureDefaultProtocol.expected (100%) rename python/ql/test/query-tests/Security/{CWE-327-InsecureProtocol => CWE-327-InsecureDefaultProtocol}/InsecureDefaultProtocol.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-327-InsecureProtocol => CWE-327-InsecureDefaultProtocol}/InsecureProtocol.py (100%) diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureDefaultProtocol.expected b/python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureDefaultProtocol.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureDefaultProtocol.expected rename to python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureDefaultProtocol.expected diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureDefaultProtocol.qlref b/python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureDefaultProtocol.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureDefaultProtocol.qlref rename to python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureDefaultProtocol.qlref diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.py b/python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureProtocol.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.py rename to python/ql/test/query-tests/Security/CWE-327-InsecureDefaultProtocol/InsecureProtocol.py From 5249591747f7f4058a12d4a9df513c15fec8db11 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 19 Jul 2021 16:57:00 +0200 Subject: [PATCH 128/429] Python: Fix test folder for InsecureProtocol --- .../InsecureProtocol.expected | 0 .../{CWE-327 => CWE-327-InsecureProtocol}/InsecureProtocol.py | 0 .../{CWE-327 => CWE-327-InsecureProtocol}/InsecureProtocol.qlref | 0 .../Security/{CWE-327 => CWE-327-InsecureProtocol}/options | 0 .../{CWE-327 => CWE-327-InsecureProtocol}/pyOpenSSL_fluent.py | 0 .../Security/{CWE-327 => CWE-327-InsecureProtocol}/ssl_fluent.py | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/InsecureProtocol.expected (100%) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/InsecureProtocol.py (100%) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/InsecureProtocol.qlref (100%) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/options (100%) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/pyOpenSSL_fluent.py (100%) rename python/ql/test/query-tests/Security/{CWE-327 => CWE-327-InsecureProtocol}/ssl_fluent.py (100%) diff --git a/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.expected rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected diff --git a/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.py rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.py diff --git a/python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.qlref b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.qlref similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/InsecureProtocol.qlref rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.qlref diff --git a/python/ql/test/query-tests/Security/CWE-327/options b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/options similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/options rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/options diff --git a/python/ql/test/query-tests/Security/CWE-327/pyOpenSSL_fluent.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/pyOpenSSL_fluent.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/pyOpenSSL_fluent.py rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/pyOpenSSL_fluent.py diff --git a/python/ql/test/query-tests/Security/CWE-327/ssl_fluent.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/ssl_fluent.py similarity index 100% rename from python/ql/test/query-tests/Security/CWE-327/ssl_fluent.py rename to python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/ssl_fluent.py From 930d576cfb2f241c6fc843d88f4ec7b5f4de7b3c Mon Sep 17 00:00:00 2001 From: Shawn P Date: Fri, 23 Jul 2021 00:45:02 +0800 Subject: [PATCH 129/429] Fixed `isUncertain()` description --- .../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 d88b8b10d57..756740790bd 100644 --- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst @@ -694,7 +694,7 @@ Furthermore, there are three member predicates that indicate the quality of the - ``DataFlow::InvokeNode.isImprecise()``: holds for invocations where the call graph builder might infer spurious call targets. - ``DataFlow::InvokeNode.isIncomplete()``: holds for invocations where the call graph builder might fail to infer possible call targets. -- ``DataFlow::InvokeNode.isUncertain()``: holds if either ``isImprecise()`` or ``isUncertain()`` holds. +- ``DataFlow::InvokeNode.isUncertain()``: holds if either ``isImprecise()`` or ``isIncomplete()`` holds. As an example of a call-graph-based query, here is a query to find invocations for which the call graph builder could not find any callees, despite the analysis being complete for this invocation: From 3bcb46f875b1ecb11e9e8a86febd90e7fc735041 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 29 Jul 2021 14:46:29 +0100 Subject: [PATCH 130/429] Model guava cache package --- .../code/java/frameworks/guava/Cache.qll | 28 +++++++++++++++++++ .../code/java/frameworks/guava/Guava.qll | 1 + 2 files changed, 29 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/guava/Cache.qll diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll new file mode 100644 index 00000000000..4134158a975 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll @@ -0,0 +1,28 @@ +/** Flow steps through methods of `com.google.common.cache` */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class GuavaBaseCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; signature; ext; input; output; kind` + "com.google.common.cache;Cache;true;asMap;();;MapKey of Argument[-1];MapKey of ReturnValue;value", + "com.google.common.cache;Cache;true;asMap;();;MapValue of Argument[-1];MapValue of ReturnValue;value", + // lambda flow from Argument[1] not implemented + "com.google.common.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value", + "com.google.common.cache;Cache;true;getIfPresent;(Object);;MapValue of Argument[-1];ReturnValue;value", + "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value", + "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[0];MapKey of Argument[-1];value", + "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[1];MapValue of Argument[-1];value", + "com.google.common.cache;Cache;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + "com.google.common.cache;Cache;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", + "com.google.common.cache;LoadingCache;true;get;(Object);;MapValue of Argument[-1];ReturnValue;value", + "com.google.common.cache;LoadingCache;true;getUnchecked;(Object);;MapValue of Argument[-1];ReturnValue;value", + "com.google.common.cache;LoadingCache;true;apply;(Object);;MapValue of Argument[-1];ReturnValue;value", + "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value", + "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" + ] + } +} 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 629ac74b426..d7a4ab959df 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Guava.qll @@ -6,3 +6,4 @@ import java import Base import Collections import IO +import Cache From 096509b9aa3ddf77b4640de4a74278021f92d34d Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 29 Jul 2021 15:01:50 +0100 Subject: [PATCH 131/429] Generate tests and stubs --- .../guava/generated/cache/Test.java | 138 +++++++++++ .../frameworks/guava/generated/cache/options | 1 + .../guava/generated/cache/test.expected | 0 .../frameworks/guava/generated/cache/test.ql | 67 ++++++ .../com/google/common/base/Function.java | 26 +-- .../com/google/common/cache/Cache.java | 25 ++ .../com/google/common/cache/CacheStats.java | 27 +++ .../com/google/common/cache/LoadingCache.java | 18 ++ .../common/collect/AbstractMultimap.java | 115 +++------ .../common/collect/BaseImmutableMultimap.java | 10 + .../common/collect/ImmutableCollection.java | 78 +++---- .../google/common/collect/ImmutableList.java | 160 ++++++------- .../google/common/collect/ImmutableMap.java | 220 +++++++----------- .../common/collect/ImmutableMultimap.java | 190 ++++++--------- .../common/collect/ImmutableMultiset.java | 172 +++++--------- ...eMultisetGwtSerializationDependencies.java | 10 + .../google/common/collect/ImmutableSet.java | 128 ++++------ .../common/collect/ImmutableSetMultimap.java | 54 +++++ .../com/google/common/collect/Multimap.java | 81 ++----- .../com/google/common/collect/Multiset.java | 76 +++--- .../google/common/collect/SetMultimap.java | 18 ++ .../common/collect/UnmodifiableIterator.java | 11 + .../collect/UnmodifiableListIterator.java | 13 ++ 23 files changed, 853 insertions(+), 785 deletions(-) create mode 100644 java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java create mode 100644 java/ql/test/library-tests/frameworks/guava/generated/cache/options create mode 100644 java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected create mode 100644 java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/Cache.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheStats.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/LoadingCache.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/SetMultimap.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableIterator.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableListIterator.java diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java new file mode 100644 index 00000000000..877c886f66a --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java @@ -0,0 +1,138 @@ +package generatedtest; + +import com.google.common.cache.Cache; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object getMapKey(Object container) { return null; } + Object getMapValue(Object container) { return null; } + Object newWithElement(Object element) { return null; } + Object newWithMapKey(Object element) { return null; } + Object newWithMapValue(Object element) { return null; } + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "com.google.common.cache;Cache;true;asMap;();;MapKey of Argument[-1];MapKey of ReturnValue;value" + ConcurrentMap out = null; + LoadingCache in = (LoadingCache)newWithMapKey(source()); + out = in.asMap(); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;asMap;();;MapKey of Argument[-1];MapKey of ReturnValue;value" + ConcurrentMap out = null; + Cache in = (Cache)newWithMapKey(source()); + out = in.asMap(); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;asMap;();;MapValue of Argument[-1];MapValue of ReturnValue;value" + ConcurrentMap out = null; + LoadingCache in = (LoadingCache)newWithMapValue(source()); + out = in.asMap(); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;asMap;();;MapValue of Argument[-1];MapValue of ReturnValue;value" + ConcurrentMap out = null; + Cache in = (Cache)newWithMapValue(source()); + out = in.asMap(); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + Cache in = (Cache)newWithMapValue(source()); + out = in.get(null, null); + sink(out); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" + ImmutableMap out = null; + Cache in = (Cache)newWithMapValue(source()); + out = in.getAllPresent(null); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;getIfPresent;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + Cache in = (Cache)newWithMapValue(source()); + out = in.getIfPresent(null); + sink(out); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[0];MapKey of Argument[-1];value" + Cache out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[1];MapValue of Argument[-1];value" + Cache out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" + Cache out = null; + Map in = (Map)newWithMapKey(source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;Cache;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" + Cache out = null; + Map in = (Map)newWithMapValue(source()); + out.putAll(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;LoadingCache;true;apply;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + LoadingCache in = (LoadingCache)newWithMapValue(source()); + out = in.apply(null); + sink(out); // $ hasValueFlow + } + { + // "com.google.common.cache;LoadingCache;true;get;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + LoadingCache in = (LoadingCache)newWithMapValue(source()); + out = in.get(null); + sink(out); // $ hasValueFlow + } + { + // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value" + ImmutableMap out = null; + Iterable in = (Iterable)newWithElement(source()); + LoadingCache instance = null; + out = instance.getAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" + ImmutableMap out = null; + LoadingCache in = (LoadingCache)newWithMapValue(source()); + out = in.getAll(null); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "com.google.common.cache;LoadingCache;true;getUnchecked;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + LoadingCache in = (LoadingCache)newWithMapValue(source()); + out = in.getUnchecked(null); + sink(out); // $ hasValueFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/options b/java/ql/test/library-tests/frameworks/guava/generated/cache/options new file mode 100644 index 00000000000..c894bb5413e --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/guava-30.0 \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql new file mode 100644 index 00000000000..f280580a5a7 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql @@ -0,0 +1,67 @@ +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest + +class SummaryModelTest extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + "generatedtest;Test;false;newWithElement;;;Argument[0];Element of ReturnValue;value", + "generatedtest;Test;false;getMapKey;;;MapKey of Argument[0];ReturnValue;value", + "generatedtest;Test;false;newWithMapKey;;;Argument[0];MapKey of ReturnValue;value", + "generatedtest;Test;false;getMapValue;;;MapValue of Argument[0];ReturnValue;value", + "generatedtest;Test;false;newWithMapValue;;;Argument[0];MapValue of ReturnValue;value" + ] + } +} + +class ValueFlowConf extends DataFlow::Configuration { + ValueFlowConf() { this = "qltest:valueFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class TaintFlowConf extends TaintTracking::Configuration { + TaintFlowConf() { this = "qltest:taintFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | + conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java index 75acf7f8a54..b5d12261264 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Function.java @@ -1,25 +1,9 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.base.Function for testing purposes, and adjusted manually package com.google.common.base; -import org.checkerframework.checker.nullness.qual.Nullable; - -public interface Function extends java.util.function.Function { - @Override - T apply(@Nullable F input); - - @Override - boolean equals(@Nullable Object object); +public interface Function extends java.util.function.Function +{ + T apply(F p0); + boolean equals(Object p0); } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/Cache.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/Cache.java new file mode 100644 index 00000000000..e509bbc8b97 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/Cache.java @@ -0,0 +1,25 @@ +// Generated automatically from com.google.common.cache.Cache for testing purposes + +package com.google.common.cache; + +import com.google.common.cache.CacheStats; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; + +public interface Cache +{ + CacheStats stats(); + ConcurrentMap asMap(); + ImmutableMap getAllPresent(Iterable p0); + V get(K p0, Callable p1); + V getIfPresent(Object p0); + long size(); + void cleanUp(); + void invalidate(Object p0); + void invalidateAll(); + void invalidateAll(Iterable p0); + void put(K p0, V p1); + void putAll(Map p0); +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheStats.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheStats.java new file mode 100644 index 00000000000..fbd5ba9656a --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheStats.java @@ -0,0 +1,27 @@ +// Generated automatically from com.google.common.cache.CacheStats for testing purposes + +package com.google.common.cache; + + +public class CacheStats +{ + protected CacheStats() {} + public CacheStats minus(CacheStats p0){ return null; } + public CacheStats plus(CacheStats p0){ return null; } + public CacheStats(long p0, long p1, long p2, long p3, long p4, long p5){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public double averageLoadPenalty(){ return 0; } + public double hitRate(){ return 0; } + public double loadExceptionRate(){ return 0; } + public double missRate(){ return 0; } + public int hashCode(){ return 0; } + public long evictionCount(){ return 0; } + public long hitCount(){ return 0; } + public long loadCount(){ return 0; } + public long loadExceptionCount(){ return 0; } + public long loadSuccessCount(){ return 0; } + public long missCount(){ return 0; } + public long requestCount(){ return 0; } + public long totalLoadTime(){ return 0; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/LoadingCache.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/LoadingCache.java new file mode 100644 index 00000000000..3918ace190d --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/LoadingCache.java @@ -0,0 +1,18 @@ +// Generated automatically from com.google.common.cache.LoadingCache for testing purposes + +package com.google.common.cache; + +import com.google.common.base.Function; +import com.google.common.cache.Cache; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.ConcurrentMap; + +public interface LoadingCache extends Cache, Function +{ + ConcurrentMap asMap(); + ImmutableMap getAll(Iterable p0); + V apply(K p0); + V get(K p0); + V getUnchecked(K p0); + void refresh(K p0); +} 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 index 0b9120bfd8b..e670680077c 100644 --- 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 @@ -1,90 +1,41 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.AbstractMultimap for testing purposes package com.google.common.collect; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; import java.util.Collection; +import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; +import java.util.Spliterator; -abstract class AbstractMultimap implements Multimap { - @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 values) { - return false; - } - - @Override - public boolean putAll(Multimap multimap) { - return false; - } - - @Override - public Collection replaceValues(K key, Iterable values) { - return null; - } - - @Override - public Collection> entries() { - return null; - } - - @Override - public Set keySet() { - return null; - } - - @Override - public Multiset keys() { - return null; - } - - @Override - public Collection values() { - return null; - } - - @Override - public Map> asMap() { - return null; - } - +abstract class AbstractMultimap implements Multimap +{ + AbstractMultimap(){} + Iterator valueIterator(){ return null; } + Spliterator> entrySpliterator(){ return null; } + Spliterator valueSpliterator(){ return null; } + abstract Collection> createEntries(); + abstract Collection createValues(); + abstract Iterator> entryIterator(); + abstract Map> createAsMap(); + abstract Multiset createKeys(); + abstract Set createKeySet(); + public Collection> entries(){ return null; } + public Collection replaceValues(K p0, Iterable p1){ return null; } + public Collection values(){ return null; } + public Map> asMap(){ return null; } + public Multiset keys(){ return null; } + public Set keySet(){ return null; } + public String toString(){ return null; } + public boolean containsEntry(Object p0, Object p1){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean put(K p0, V p1){ return false; } + public boolean putAll(K p0, Iterable p1){ return false; } + public boolean putAll(Multimap p0){ return false; } + public boolean remove(Object p0, Object p1){ return false; } + public int hashCode(){ return 0; } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java new file mode 100644 index 00000000000..5fba2033c73 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java @@ -0,0 +1,10 @@ +// Generated automatically from com.google.common.collect.BaseImmutableMultimap for testing purposes + +package com.google.common.collect; + +import com.google.common.collect.AbstractMultimap; + +abstract class BaseImmutableMultimap extends AbstractMultimap +{ + BaseImmutableMultimap(){} +} 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 index 670016cdab6..dc3c1ebfc9c 100644 --- 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 @@ -1,50 +1,48 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableCollection for testing purposes package com.google.common.collect; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.UnmodifiableIterator; import java.io.Serializable; import java.util.AbstractCollection; import java.util.Collection; import java.util.Iterator; +import java.util.Spliterator; +import java.util.function.Predicate; -public abstract class ImmutableCollection extends AbstractCollection implements Serializable { - ImmutableCollection() {} - - public ImmutableList asList() { - return null; - } - - public abstract static class Builder { - Builder() {} - - public abstract Builder add(E element); - - public Builder add(E... elements) { - return null; +abstract public class ImmutableCollection extends AbstractCollection implements Serializable +{ + ImmutableCollection(){} + Object writeReplace(){ return null; } + Object[] internalArray(){ return null; } + abstract boolean isPartialView(); + abstract static public class Builder + { + Builder(){} + public ImmutableCollection.Builder add(E... p0){ return null; } + public ImmutableCollection.Builder addAll(Iterable p0){ return null; } + public ImmutableCollection.Builder addAll(Iterator p0){ return null; } + public abstract ImmutableCollection.Builder add(E p0); + public abstract ImmutableCollection build(); + static int DEFAULT_INITIAL_CAPACITY = 0; + static int expandedCapacity(int p0, int p1){ return 0; } } - - public Builder addAll(Iterable elements) { - return null; - } - - public Builder addAll(Iterator elements) { - return null; - } - - public abstract ImmutableCollection build(); - } + int copyIntoArray(Object[] p0, int p1){ return 0; } + int internalArrayEnd(){ return 0; } + int internalArrayStart(){ return 0; } + public ImmutableList asList(){ return null; } + public Spliterator spliterator(){ return null; } + public abstract UnmodifiableIterator iterator(); + public abstract boolean contains(Object p0); + public final T[] toArray(T[] p0){ return null; } + public final Object[] toArray(){ return null; } + public final boolean add(E p0){ return false; } + public final boolean addAll(Collection p0){ return false; } + public final boolean remove(Object p0){ return false; } + public final boolean removeAll(Collection p0){ return false; } + public final boolean removeIf(Predicate p0){ return false; } + public final boolean retainAll(Collection p0){ return false; } + public final void clear(){} + static int SPLITERATOR_CHARACTERISTICS = 0; } 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 index 3e4fcf39d0a..2252c3b692d 100644 --- 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 @@ -1,101 +1,79 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableList for testing purposes package com.google.common.collect; -import java.util.Arrays; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.UnmodifiableIterator; +import com.google.common.collect.UnmodifiableListIterator; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.RandomAccess; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.UnaryOperator; +import java.util.stream.Collector; -public abstract class ImmutableList extends ImmutableCollection - implements List{ - - public static ImmutableList of() { - return null; - } - - public static ImmutableList of(E element) { - return null; - } - - public static ImmutableList of(E e1, E e2) { - return null; - } - - public static ImmutableList of(E e1, E e2, E e3) { - return null; - } - - public static ImmutableList of(E e1, E e2, E e3, E e4) { - return null; - } - - public static ImmutableList 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 ImmutableList copyOf(Iterable elements) { - return null; - } - - public static ImmutableList copyOf(Collection elements) { - return null; - } - - public static ImmutableList copyOf(Iterator elements) { - return null; - } - - public static ImmutableList copyOf(E[] elements) { - return null; - } - - public static > ImmutableList sortedCopyOf( - Iterable elements) { - return null; - } - - public static ImmutableList sortedCopyOf( - Comparator comparator, Iterable elements) { - return null; - } - - ImmutableList() {} - - public ImmutableList reverse() { - return null; - } - - public static Builder builder() { - return null; - } - - public static final class Builder extends ImmutableCollection.Builder { - @Override - public Builder add(E element) { - return null; +abstract public class ImmutableList extends ImmutableCollection implements List, RandomAccess +{ + ImmutableList(){} + ImmutableList subListUnchecked(int p0, int p1){ return null; } + Object writeReplace(){ return null; } + int copyIntoArray(Object[] p0, int p1){ return 0; } + public ImmutableList reverse(){ return null; } + public ImmutableList subList(int p0, int p1){ return null; } + public Spliterator spliterator(){ return null; } + public UnmodifiableIterator iterator(){ return null; } + public UnmodifiableListIterator listIterator(){ return null; } + public UnmodifiableListIterator listIterator(int p0){ return null; } + public boolean contains(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public final E remove(int p0){ return null; } + public final E set(int p0, E p1){ return null; } + public final ImmutableList asList(){ return null; } + public final boolean addAll(int p0, Collection p1){ return false; } + public final void add(int p0, E p1){} + public final void replaceAll(UnaryOperator p0){} + public final void sort(Comparator p0){} + public int hashCode(){ return 0; } + public int indexOf(Object p0){ return 0; } + public int lastIndexOf(Object p0){ return 0; } + public static > ImmutableList sortedCopyOf(Iterable p0){ return null; } + public static Collector> toImmutableList(){ return null; } + public static ImmutableList.Builder builder(){ return null; } + public static ImmutableList.Builder builderWithExpectedSize(int p0){ return null; } + public static ImmutableList copyOf(Collection p0){ return null; } + public static ImmutableList copyOf(E[] p0){ return null; } + public static ImmutableList copyOf(Iterable p0){ return null; } + public static ImmutableList copyOf(Iterator p0){ return null; } + public static ImmutableList of(){ return null; } + public static ImmutableList of(E p0){ return null; } + public static ImmutableList of(E p0, E p1){ return null; } + public static ImmutableList of(E p0, E p1, E p2){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7, E p8){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7, E p8, E p9){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7, E p8, E p9, E p10){ return null; } + public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7, E p8, E p9, E p10, E p11, E... p12){ return null; } + public static ImmutableList sortedCopyOf(Comparator p0, Iterable p1){ return null; } + public void forEach(Consumer p0){} + static ImmutableList asImmutableList(Object[] p0){ return null; } + static ImmutableList asImmutableList(Object[] p0, int p1){ return null; } + static public class Builder extends ImmutableCollection.Builder + { + Builder(int p0){} + ImmutableList.Builder combine(ImmutableList.Builder p0){ return null; } + Object[] contents = null; + public Builder(){} + public ImmutableList.Builder add(E p0){ return null; } + public ImmutableList.Builder add(E... p0){ return null; } + public ImmutableList.Builder addAll(Iterable p0){ return null; } + public ImmutableList.Builder addAll(Iterator p0){ return null; } + public ImmutableList build(){ return null; } } - - @Override - public ImmutableList 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 index 631d25768fb..cae21e11cc5 100644 --- 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 @@ -1,149 +1,87 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableMap for testing purposes package com.google.common.collect; -import java.util.Collection; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; import java.util.Comparator; import java.util.Map; +import java.util.Spliterator; +import java.util.function.BiFunction; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collector; -public abstract class ImmutableMap implements Map { - public static ImmutableMap of() { - return null; - } - - public static ImmutableMap of(K k1, V v1) { - return null; - } - - public static ImmutableMap of(K k1, V v1, K k2, V v2) { - return null; - } - - public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3) { - return null; - } - - public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { - return null; - } - - public static ImmutableMap 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 Builder builder() { - return null; - } - - public static Builder builderWithExpectedSize(int expectedSize) { - return null; - } - - public static class Builder { - public Builder() { +abstract public class ImmutableMap implements Map, Serializable +{ + ImmutableMap(){} + Object writeReplace(){ return null; } + Spliterator keySpliterator(){ return null; } + UnmodifiableIterator keyIterator(){ return null; } + abstract ImmutableCollection createValues(); + abstract ImmutableSet createKeySet(); + abstract ImmutableSet> createEntrySet(); + abstract boolean isPartialView(); + boolean isHashCodeFast(){ return false; } + public ImmutableCollection values(){ return null; } + public ImmutableSet keySet(){ return null; } + public ImmutableSet> entrySet(){ return null; } + public ImmutableSetMultimap asMultimap(){ return null; } + public String toString(){ return null; } + public abstract V get(Object p0); + public boolean containsKey(Object p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public final V compute(K p0, BiFunction p1){ return null; } + public final V computeIfAbsent(K p0, Function p1){ return null; } + public final V computeIfPresent(K p0, BiFunction p1){ return null; } + public final V getOrDefault(Object p0, V p1){ return null; } + public final V merge(K p0, V p1, BiFunction p2){ return null; } + public final V put(K p0, V p1){ return null; } + public final V putIfAbsent(K p0, V p1){ return null; } + public final V remove(Object p0){ return null; } + public final V replace(K p0, V p1){ return null; } + public final boolean remove(Object p0, Object p1){ return false; } + public final boolean replace(K p0, V p1, V p2){ return false; } + public final void clear(){} + public final void putAll(Map p0){} + public final void replaceAll(BiFunction p0){} + public int hashCode(){ return 0; } + public static ImmutableMap.Builder builder(){ return null; } + public static ImmutableMap.Builder builderWithExpectedSize(int p0){ return null; } + public static ImmutableMap copyOf(Iterable> p0){ return null; } + public static ImmutableMap copyOf(Map p0){ return null; } + public static ImmutableMap of(){ return null; } + public static ImmutableMap of(K p0, V p1){ return null; } + public static ImmutableMap of(K p0, V p1, K p2, V p3){ return null; } + public static ImmutableMap of(K p0, V p1, K p2, V p3, K p4, V p5){ return null; } + public static ImmutableMap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7){ return null; } + public static ImmutableMap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7, K p8, V p9){ return null; } + public static Collector> toImmutableMap(Function p0, Function p1){ return null; } + public static Collector> toImmutableMap(Function p0, Function p1, BinaryOperator p2){ return null; } + static Map.Entry entryOf(K p0, V p1){ return null; } + static IllegalArgumentException conflictException(String p0, Object p1, Object p2){ return null; } + static Map.Entry[] EMPTY_ENTRY_ARRAY = null; + static public class Builder + { + Builder(int p0){} + Comparator valueComparator = null; + ImmutableMap.Builder combine(ImmutableMap.Builder p0){ return null; } + ImmutableMap buildJdkBacked(){ return null; } + Map.Entry[] entries = null; + boolean entriesUsed = false; + int size = 0; + public Builder(){} + public ImmutableMap.Builder orderEntriesByValue(Comparator p0){ return null; } + public ImmutableMap.Builder put(K p0, V p1){ return null; } + public ImmutableMap.Builder put(Map.Entry p0){ return null; } + public ImmutableMap.Builder putAll(Iterable> p0){ return null; } + public ImmutableMap.Builder putAll(Map p0){ return null; } + public ImmutableMap build(){ return null; } } - - public Builder put(K key, V value) { - return null; - } - - public Builder put(Entry entry) { - return null; - } - - public Builder putAll(Map map) { - return null; - } - - public Builder putAll(Iterable> entries) { - return null; - } - - public Builder orderEntriesByValue(Comparator valueComparator) { - return null; - } - - public ImmutableMap build() { - return null; - } - - } - public static ImmutableMap copyOf(Map map) { - return null; - } - - public static ImmutableMap copyOf( - Iterable> entries) { - return null; - } - - @Override - public final V put(K k, V v) { - return null; - } - - @Override - public final void putAll(Map 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> entrySet() { - return null; - } - - @Override - public ImmutableSet keySet() { - return null; - } - - @Override - public ImmutableCollection values() { - return null; - } - - // public ImmutableSetMultimap asMultimap() { - // return null; - // } + static void checkNoConflict(boolean p0, String p1, Map.Entry p2, Map.Entry p3){} } 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 index c1345f72f3f..8e00b81f81d 100644 --- 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 @@ -1,128 +1,80 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableMultimap for testing purposes package com.google.common.collect; +import com.google.common.collect.BaseImmutableMultimap; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.UnmodifiableIterator; +import java.io.Serializable; import java.util.Collection; import java.util.Comparator; import java.util.Map; -import java.util.Map.Entry; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.BiConsumer; -public abstract class ImmutableMultimap extends AbstractMultimap { - public static ImmutableMultimap of() { - return null; - } - - public static ImmutableMultimap of(K k1, V v1) { - return null; - } - - public static ImmutableMultimap of(K k1, V v1, K k2, V v2) { - return null; - } - - public static ImmutableMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) { - return null; - } - - public static ImmutableMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) { - return null; - } - - public static ImmutableMultimap 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 Builder builder() { - return null; - } - - public static class Builder { - public Builder() { +abstract public class ImmutableMultimap extends BaseImmutableMultimap implements Serializable +{ + protected ImmutableMultimap() {} + ImmutableCollection> createEntries(){ return null; } + ImmutableCollection createValues(){ return null; } + ImmutableMultimap(ImmutableMap> p0, int p1){} + ImmutableMultiset createKeys(){ return null; } + Map> createAsMap(){ return null; } + Set createKeySet(){ return null; } + Spliterator> entrySpliterator(){ return null; } + UnmodifiableIterator> entryIterator(){ return null; } + UnmodifiableIterator valueIterator(){ return null; } + boolean isPartialView(){ return false; } + final ImmutableMap> map = null; + final int size = 0; + public ImmutableCollection> entries(){ return null; } + public ImmutableCollection removeAll(Object p0){ return null; } + public ImmutableCollection replaceValues(K p0, Iterable p1){ return null; } + public ImmutableCollection values(){ return null; } + public ImmutableMap> asMap(){ return null; } + public ImmutableMultiset keys(){ return null; } + public ImmutableSet keySet(){ return null; } + public abstract ImmutableCollection get(K p0); + public abstract ImmutableMultimap inverse(); + public boolean containsKey(Object p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean put(K p0, V p1){ return false; } + public boolean putAll(K p0, Iterable p1){ return false; } + public boolean putAll(Multimap p0){ return false; } + public boolean remove(Object p0, Object p1){ return false; } + public int size(){ return 0; } + public static ImmutableMultimap.Builder builder(){ return null; } + public static ImmutableMultimap copyOf(Iterable> p0){ return null; } + public static ImmutableMultimap copyOf(Multimap p0){ return null; } + public static ImmutableMultimap of(){ return null; } + public static ImmutableMultimap of(K p0, V p1){ return null; } + public static ImmutableMultimap of(K p0, V p1, K p2, V p3){ return null; } + public static ImmutableMultimap of(K p0, V p1, K p2, V p3, K p4, V p5){ return null; } + public static ImmutableMultimap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7){ return null; } + public static ImmutableMultimap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7, K p8, V p9){ return null; } + public void clear(){} + public void forEach(BiConsumer p0){} + static public class Builder + { + Collection newMutableValueCollection(){ return null; } + Comparator keyComparator = null; + Comparator valueComparator = null; + ImmutableMultimap.Builder combine(ImmutableMultimap.Builder p0){ return null; } + Map> builderMap = null; + public Builder(){} + public ImmutableMultimap.Builder orderKeysBy(Comparator p0){ return null; } + public ImmutableMultimap.Builder orderValuesBy(Comparator p0){ return null; } + public ImmutableMultimap.Builder put(K p0, V p1){ return null; } + public ImmutableMultimap.Builder put(Map.Entry p0){ return null; } + public ImmutableMultimap.Builder putAll(Iterable> p0){ return null; } + public ImmutableMultimap.Builder putAll(K p0, Iterable p1){ return null; } + public ImmutableMultimap.Builder putAll(K p0, V... p1){ return null; } + public ImmutableMultimap.Builder putAll(Multimap p0){ return null; } + public ImmutableMultimap build(){ return null; } } - - public Builder put(K key, V value) { - return null; - } - - public Builder put(Entry entry) { - return null; - } - - public Builder putAll(Iterable> entries) { - return null; - } - - public Builder putAll(K key, Iterable values) { - return null; - } - - public Builder putAll(K key, V... values) { - return null; - } - - public Builder putAll(Multimap multimap) { - return null; - } - - public Builder orderKeysBy(Comparator keyComparator) { - return null; - } - - public Builder orderValuesBy(Comparator valueComparator) { - return null; - } - - public ImmutableMultimap build() { - return null; - } - - } - public static ImmutableMultimap copyOf(Multimap multimap) { - return null; - } - - public static ImmutableMultimap copyOf( - Iterable> entries) { - return null; - } - - @Override - public ImmutableCollection removeAll(Object key) { - return null; - } - - @Override - public void clear() { - } - - @Override - public abstract ImmutableCollection get(K key); - - public abstract ImmutableMultimap 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 index 0fb82a18c80..c78654fdc14 100644 --- 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 @@ -1,125 +1,63 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableMultiset for testing purposes package com.google.common.collect; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultisetGwtSerializationDependencies; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multiset; +import com.google.common.collect.UnmodifiableIterator; import java.util.Collection; import java.util.Iterator; +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.stream.Collector; -public abstract class ImmutableMultiset extends ImmutableCollection - implements Multiset { - - public static ImmutableMultiset of() { - return null; - } - - public static ImmutableMultiset of(E element) { - return null; - } - - public static ImmutableMultiset of(E e1, E e2) { - return null; - } - - public static ImmutableMultiset of(E e1, E e2, E e3) { - return null; - } - - public static ImmutableMultiset of(E e1, E e2, E e3, E e4) { - return null; - } - - public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5) { - return null; - } - - public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { - return null; - } - - public static ImmutableMultiset copyOf(E[] elements) { - return null; - } - - public static ImmutableMultiset copyOf(Iterable elements) { - return null; - } - - public static ImmutableMultiset copyOf(Iterator 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 elementSet(); - - @Override - public ImmutableSet> entrySet() { - return null; - } - - public static Builder builder() { - return null; - } - - public static class Builder extends ImmutableCollection.Builder { - public Builder() { +abstract public class ImmutableMultiset extends ImmutableMultisetGwtSerializationDependencies implements Multiset +{ + ImmutableMultiset(){} + Object writeReplace(){ return null; } + abstract Multiset.Entry getEntry(int p0); + int copyIntoArray(Object[] p0, int p1){ return 0; } + public ImmutableList asList(){ return null; } + public ImmutableSet> entrySet(){ return null; } + public String toString(){ return null; } + public UnmodifiableIterator iterator(){ return null; } + public abstract ImmutableSet elementSet(); + public boolean contains(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public final boolean setCount(E p0, int p1, int p2){ return false; } + public final int add(E p0, int p1){ return 0; } + public final int remove(Object p0, int p1){ return 0; } + public final int setCount(E p0, int p1){ return 0; } + public int hashCode(){ return 0; } + public static Collector> toImmutableMultiset(){ return null; } + public static ImmutableMultiset.Builder builder(){ return null; } + public static ImmutableMultiset copyOf(E[] p0){ return null; } + public static ImmutableMultiset copyOf(Iterable p0){ return null; } + public static ImmutableMultiset copyOf(Iterator p0){ return null; } + public static ImmutableMultiset of(){ return null; } + public static ImmutableMultiset of(E p0){ return null; } + public static ImmutableMultiset of(E p0, E p1){ return null; } + public static ImmutableMultiset of(E p0, E p1, E p2){ return null; } + public static ImmutableMultiset of(E p0, E p1, E p2, E p3){ return null; } + public static ImmutableMultiset of(E p0, E p1, E p2, E p3, E p4){ return null; } + public static ImmutableMultiset of(E p0, E p1, E p2, E p3, E p4, E p5, E... p6){ return null; } + public static Collector> toImmutableMultiset(Function p0, ToIntFunction p1){ return null; } + static ImmutableMultiset copyFromEntries(Collection> p0){ return null; } + static public class Builder extends ImmutableCollection.Builder + { + Builder(Multiset p0){} + ImmutableMultiset buildJdkBacked(){ return null; } + final Multiset contents = null; + public Builder(){} + public ImmutableMultiset.Builder add(E p0){ return null; } + public ImmutableMultiset.Builder add(E... p0){ return null; } + public ImmutableMultiset.Builder addAll(Iterable p0){ return null; } + public ImmutableMultiset.Builder addAll(Iterator p0){ return null; } + public ImmutableMultiset.Builder addCopies(E p0, int p1){ return null; } + public ImmutableMultiset.Builder setCount(E p0, int p1){ return null; } + public ImmutableMultiset build(){ return null; } } - - @Override - public Builder add(E element) { - return null; - } - - public Builder addCopies(E element, int occurrences) { - return null; - } - - public Builder setCount(E element, int count) { - return null; - } - - @Override - public ImmutableMultiset build() { - return null; - } - - } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java new file mode 100644 index 00000000000..b489a250e27 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java @@ -0,0 +1,10 @@ +// Generated automatically from com.google.common.collect.ImmutableMultisetGwtSerializationDependencies for testing purposes + +package com.google.common.collect; + +import com.google.common.collect.ImmutableCollection; + +abstract class ImmutableMultisetGwtSerializationDependencies extends ImmutableCollection +{ + ImmutableMultisetGwtSerializationDependencies(){} +} 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 index 938b5aedf59..a277e287390 100644 --- 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 @@ -1,86 +1,60 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.ImmutableSet for testing purposes package com.google.common.collect; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.UnmodifiableIterator; import java.util.Collection; import java.util.Iterator; import java.util.Set; +import java.util.stream.Collector; -public abstract class ImmutableSet extends ImmutableCollection implements Set { - public static ImmutableSet of() { - return null; - } - - public static ImmutableSet of(E element) { - return null; - } - - public static ImmutableSet of(E e1, E e2) { - return null; - } - - public static ImmutableSet of(E e1, E e2, E e3) { - return null; - } - - public static ImmutableSet of(E e1, E e2, E e3, E e4) { - return null; - } - - public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5) { - return null; - } - - public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) { - return null; - } - - public static ImmutableSet copyOf(Collection elements) { - return null; - } - - public static ImmutableSet copyOf(Iterable elements) { - return null; - } - - public static ImmutableSet copyOf(Iterator elements) { - return null; - } - - public static ImmutableSet copyOf(E[] elements) { - return null; - } - - ImmutableSet() {} - - public static Builder builder() { - return null; - } - - public static class Builder extends ImmutableCollection.Builder { - public Builder() { +abstract public class ImmutableSet extends ImmutableCollection implements Set +{ + ImmutableList createAsList(){ return null; } + ImmutableSet(){} + Object writeReplace(){ return null; } + boolean isHashCodeFast(){ return false; } + public ImmutableList asList(){ return null; } + public abstract UnmodifiableIterator iterator(); + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static Collector> toImmutableSet(){ return null; } + public static ImmutableSet.Builder builder(){ return null; } + public static ImmutableSet.Builder builderWithExpectedSize(int p0){ return null; } + public static ImmutableSet copyOf(Collection p0){ return null; } + public static ImmutableSet copyOf(E[] p0){ return null; } + public static ImmutableSet copyOf(Iterable p0){ return null; } + public static ImmutableSet copyOf(Iterator p0){ return null; } + public static ImmutableSet of(){ return null; } + public static ImmutableSet of(E p0){ return null; } + public static ImmutableSet of(E p0, E p1){ return null; } + public static ImmutableSet of(E p0, E p1, E p2){ return null; } + public static ImmutableSet of(E p0, E p1, E p2, E p3){ return null; } + public static ImmutableSet of(E p0, E p1, E p2, E p3, E p4){ return null; } + public static ImmutableSet of(E p0, E p1, E p2, E p3, E p4, E p5, E... p6){ return null; } + static Object[] rebuildHashTable(int p0, Object[] p1, int p2){ return null; } + static boolean hashFloodingDetected(Object[] p0){ return false; } + static double HASH_FLOODING_FPP = 0; + static int MAX_RUN_MULTIPLIER = 0; + static int MAX_TABLE_SIZE = 0; + static int SPLITERATOR_CHARACTERISTICS = 0; + static int chooseTableSize(int p0){ return 0; } + static public class Builder extends ImmutableCollection.Builder + { + Builder(boolean p0){} + Builder(int p0){} + ImmutableSet.Builder combine(ImmutableSet.Builder p0){ return null; } + boolean forceCopy = false; + final void copyIfNecessary(){} + public Builder(){} + public ImmutableSet.Builder add(E p0){ return null; } + public ImmutableSet.Builder add(E... p0){ return null; } + public ImmutableSet.Builder addAll(Iterable p0){ return null; } + public ImmutableSet.Builder addAll(Iterator p0){ return null; } + public ImmutableSet build(){ return null; } + void copy(){} + void forceJdk(){} } - - public Builder add(E element) { - return null; - } - - public ImmutableSet build() { - return null; - } - } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java new file mode 100644 index 00000000000..daad9655c43 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java @@ -0,0 +1,54 @@ +// Generated automatically from com.google.common.collect.ImmutableSetMultimap for testing purposes + +package com.google.common.collect; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Stream; + +public class ImmutableSetMultimap extends ImmutableMultimap implements SetMultimap +{ + protected ImmutableSetMultimap() {} + Comparator valueComparator(){ return null; } + ImmutableSetMultimap(ImmutableMap> p0, int p1, Comparator p2){} + public ImmutableSet> entries(){ return null; } + public ImmutableSet get(K p0){ return null; } + public ImmutableSetMultimap inverse(){ return null; } + public final ImmutableSet removeAll(Object p0){ return null; } + public final ImmutableSet replaceValues(K p0, Iterable p1){ return null; } + public static ImmutableSetMultimap.Builder builder(){ return null; } + public static ImmutableSetMultimap copyOf(Iterable> p0){ return null; } + public static ImmutableSetMultimap copyOf(Multimap p0){ return null; } + public static ImmutableSetMultimap of(){ return null; } + public static ImmutableSetMultimap of(K p0, V p1){ return null; } + public static ImmutableSetMultimap of(K p0, V p1, K p2, V p3){ return null; } + public static ImmutableSetMultimap of(K p0, V p1, K p2, V p3, K p4, V p5){ return null; } + public static ImmutableSetMultimap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7){ return null; } + public static ImmutableSetMultimap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7, K p8, V p9){ return null; } + public static Collector> flatteningToImmutableSetMultimap(Function p0, Function> p1){ return null; } + public static Collector> toImmutableSetMultimap(Function p0, Function p1){ return null; } + static ImmutableSetMultimap fromMapEntries(Collection>> p0, Comparator p1){ return null; } + static public class Builder extends ImmutableMultimap.Builder + { + Collection newMutableValueCollection(){ return null; } + ImmutableSetMultimap.Builder combine(ImmutableMultimap.Builder p0){ return null; } + public Builder(){} + public ImmutableSetMultimap.Builder orderKeysBy(Comparator p0){ return null; } + public ImmutableSetMultimap.Builder orderValuesBy(Comparator p0){ return null; } + public ImmutableSetMultimap.Builder put(K p0, V p1){ return null; } + public ImmutableSetMultimap.Builder put(Map.Entry p0){ return null; } + public ImmutableSetMultimap.Builder putAll(Iterable> p0){ return null; } + public ImmutableSetMultimap.Builder putAll(K p0, Iterable p1){ return null; } + public ImmutableSetMultimap.Builder putAll(K p0, V... p1){ return null; } + public ImmutableSetMultimap.Builder putAll(Multimap p0){ return null; } + public ImmutableSetMultimap build(){ 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 index 80223a450c9..9cdec55e59c 100644 --- 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 @@ -1,65 +1,34 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.Multimap for testing purposes package com.google.common.collect; - +import com.google.common.collect.Multiset; 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 { - 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 values); - - boolean putAll(Multimap multimap); - - Collection replaceValues(K key, Iterable values); - - Collection removeAll(Object key); - - void clear(); - - Collection get(K key); - - Set keySet(); - - Multiset keys(); - - Collection values(); - - Collection> entries(); - - default void forEach(BiConsumer action) { - } - - Map> asMap(); +public interface Multimap +{ + Collection> entries(); + Collection get(K p0); + Collection removeAll(Object p0); + Collection replaceValues(K p0, Iterable p1); + Collection values(); + Map> asMap(); + Multiset keys(); + Set keySet(); + boolean containsEntry(Object p0, Object p1); + boolean containsKey(Object p0); + boolean containsValue(Object p0); + boolean equals(Object p0); + boolean isEmpty(); + boolean put(K p0, V p1); + boolean putAll(K p0, Iterable p1); + boolean putAll(Multimap p0); + boolean remove(Object p0, Object p1); + default void forEach(BiConsumer p0){} + int hashCode(); + int size(); + void clear(); } 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 index c67f63e79a0..9c6f000078c 100644 --- 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 @@ -1,49 +1,43 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.collect.Multiset for testing purposes package com.google.common.collect; - import java.util.Collection; +import java.util.Iterator; import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; import java.util.function.ObjIntConsumer; -public interface Multiset extends Collection { - 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 elementSet(); - - Set> entrySet(); - - default void forEachEntry(ObjIntConsumer action) { - } - - boolean equals(Object object); - - interface Entry { - E getElement(); - - int getCount(); - } +public interface Multiset extends Collection +{ + Iterator iterator(); + Set elementSet(); + Set> entrySet(); + String toString(); + boolean add(E p0); + boolean contains(Object p0); + boolean containsAll(Collection p0); + boolean equals(Object p0); + boolean remove(Object p0); + boolean removeAll(Collection p0); + boolean retainAll(Collection p0); + boolean setCount(E p0, int p1, int p2); + default Spliterator spliterator(){ return null; } + default void forEach(Consumer p0){} + default void forEachEntry(ObjIntConsumer p0){} + int add(E p0, int p1); + int count(Object p0); + int hashCode(); + int remove(Object p0, int p1); + int setCount(E p0, int p1); + int size(); + static public interface Entry + { + E getElement(); + String toString(); + boolean equals(Object p0); + int getCount(); + int hashCode(); + } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/SetMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/SetMultimap.java new file mode 100644 index 00000000000..07dd464de7b --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/SetMultimap.java @@ -0,0 +1,18 @@ +// Generated automatically from com.google.common.collect.SetMultimap for testing purposes + +package com.google.common.collect; + +import com.google.common.collect.Multimap; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public interface SetMultimap extends Multimap +{ + Map> asMap(); + Set> entries(); + Set get(K p0); + Set removeAll(Object p0); + Set replaceValues(K p0, Iterable p1); + boolean equals(Object p0); +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableIterator.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableIterator.java new file mode 100644 index 00000000000..4f6106eaea7 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableIterator.java @@ -0,0 +1,11 @@ +// Generated automatically from com.google.common.collect.UnmodifiableIterator for testing purposes + +package com.google.common.collect; + +import java.util.Iterator; + +abstract public class UnmodifiableIterator implements Iterator +{ + protected UnmodifiableIterator(){} + public final void remove(){} +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableListIterator.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableListIterator.java new file mode 100644 index 00000000000..24bb873d35d --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/UnmodifiableListIterator.java @@ -0,0 +1,13 @@ +// Generated automatically from com.google.common.collect.UnmodifiableListIterator for testing purposes + +package com.google.common.collect; + +import com.google.common.collect.UnmodifiableIterator; +import java.util.ListIterator; + +abstract public class UnmodifiableListIterator extends UnmodifiableIterator implements ListIterator +{ + protected UnmodifiableListIterator(){} + public final void add(E p0){} + public final void set(E p0){} +} From f1ca29a84642d020a8510320f881bf4762ea36b6 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 29 Jul 2021 15:58:42 +0100 Subject: [PATCH 132/429] Add more stubs --- .../com/google/common/base/Predicate.java | 31 +++----------- .../com/google/common/base/Supplier.java | 21 ++-------- .../com/google/common/base/Ticker.java | 11 +++++ .../google/common/cache/AbstractCache.java | 35 ++++++++++++++++ .../com/google/common/cache/CacheBuilder.java | 41 +++++++++++++++++++ .../google/common/cache/CacheBuilderSpec.java | 15 +++++++ .../com/google/common/cache/CacheLoader.java | 20 +++++++++ .../com/google/common/cache/RemovalCause.java | 10 +++++ .../google/common/cache/RemovalListener.java | 10 +++++ .../common/cache/RemovalNotification.java | 14 +++++++ .../com/google/common/cache/Weigher.java | 9 ++++ .../common/collect/AbstractMultimap.java | 12 ------ .../common/collect/BaseImmutableMultimap.java | 1 - .../common/collect/ImmutableCollection.java | 11 ----- .../google/common/collect/ImmutableList.java | 9 ---- .../google/common/collect/ImmutableMap.java | 22 ---------- .../common/collect/ImmutableMultimap.java | 20 --------- .../common/collect/ImmutableMultiset.java | 9 ---- ...eMultisetGwtSerializationDependencies.java | 1 - .../google/common/collect/ImmutableSet.java | 18 -------- .../common/collect/ImmutableSetMultimap.java | 7 ---- .../util/concurrent/ListenableFuture.java | 11 +++++ 22 files changed, 186 insertions(+), 152 deletions(-) create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/base/Ticker.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/AbstractCache.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilder.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilderSpec.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheLoader.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalCause.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalListener.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalNotification.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/cache/Weigher.java create mode 100644 java/ql/test/stubs/guava-30.0/com/google/common/util/concurrent/ListenableFuture.java diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java index 1adc6a1caed..ae2e1a9944f 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Predicate.java @@ -1,29 +1,10 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.base.Predicate for testing purposes, and adjusted manually. package com.google.common.base; -import org.checkerframework.checker.nullness.qual.Nullable; - -public interface Predicate extends java.util.function.Predicate { - boolean apply(@Nullable T input); - - @Override - boolean equals(@Nullable Object object); - - @Override - default boolean test(@Nullable T input) { - return false; - } +public interface Predicate extends java.util.function.Predicate +{ + boolean apply(T p0); + boolean equals(Object p0); + default boolean test(T p0){ return false; } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java index a9be9855c8c..0ebb8e4ea8d 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Supplier.java @@ -1,21 +1,8 @@ -/* - * 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. - */ +// Generated automatically from com.google.common.base.Supplier for testing purposes, and adjusted manually package com.google.common.base; -public interface Supplier extends java.util.function.Supplier { - @Override - T get(); - +public interface Supplier extends java.util.function.Supplier +{ + T get(); } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/base/Ticker.java b/java/ql/test/stubs/guava-30.0/com/google/common/base/Ticker.java new file mode 100644 index 00000000000..d36ff7dfd14 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/base/Ticker.java @@ -0,0 +1,11 @@ +// Generated automatically from com.google.common.base.Ticker for testing purposes + +package com.google.common.base; + + +abstract public class Ticker +{ + protected Ticker(){} + public abstract long read(); + public static Ticker systemTicker(){ return null; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/AbstractCache.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/AbstractCache.java new file mode 100644 index 00000000000..c10c6af195f --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/AbstractCache.java @@ -0,0 +1,35 @@ +// Generated automatically from com.google.common.cache.AbstractCache for testing purposes + +package com.google.common.cache; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; + +abstract public class AbstractCache implements Cache +{ + protected AbstractCache(){} + public CacheStats stats(){ return null; } + public ConcurrentMap asMap(){ return null; } + public ImmutableMap getAllPresent(Iterable p0){ return null; } + public V get(K p0, Callable p1){ return null; } + public long size(){ return 0; } + public void cleanUp(){} + public void invalidate(Object p0){} + public void invalidateAll(){} + public void invalidateAll(Iterable p0){} + public void put(K p0, V p1){} + public void putAll(Map p0){} + static public interface StatsCounter + { + CacheStats snapshot(); + void recordEviction(); + void recordHits(int p0); + void recordLoadException(long p0); + void recordLoadSuccess(long p0); + void recordMisses(int p0); + } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilder.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilder.java new file mode 100644 index 00000000000..19fe8330ca6 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilder.java @@ -0,0 +1,41 @@ +// Generated automatically from com.google.common.cache.CacheBuilder for testing purposes + +package com.google.common.cache; + +import com.google.common.base.Ticker; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilderSpec; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.Weigher; +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +public class CacheBuilder +{ + protected CacheBuilder() {} + public Cache build(){ return null; } + public CacheBuilder removalListener(RemovalListener p0){ return null; } + public CacheBuilder weigher(Weigher p0){ return null; } + public LoadingCache build(CacheLoader p0){ return null; } + public CacheBuilder concurrencyLevel(int p0){ return null; } + public CacheBuilder expireAfterAccess(Duration p0){ return null; } + public CacheBuilder expireAfterAccess(long p0, TimeUnit p1){ return null; } + public CacheBuilder expireAfterWrite(Duration p0){ return null; } + public CacheBuilder expireAfterWrite(long p0, TimeUnit p1){ return null; } + public CacheBuilder initialCapacity(int p0){ return null; } + public CacheBuilder maximumSize(long p0){ return null; } + public CacheBuilder maximumWeight(long p0){ return null; } + public CacheBuilder recordStats(){ return null; } + public CacheBuilder refreshAfterWrite(Duration p0){ return null; } + public CacheBuilder refreshAfterWrite(long p0, TimeUnit p1){ return null; } + public CacheBuilder softValues(){ return null; } + public CacheBuilder ticker(Ticker p0){ return null; } + public CacheBuilder weakKeys(){ return null; } + public CacheBuilder weakValues(){ return null; } + public String toString(){ return null; } + public static CacheBuilder from(CacheBuilderSpec p0){ return null; } + public static CacheBuilder from(String p0){ return null; } + public static CacheBuilder newBuilder(){ return null; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilderSpec.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilderSpec.java new file mode 100644 index 00000000000..120026f761e --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheBuilderSpec.java @@ -0,0 +1,15 @@ +// Generated automatically from com.google.common.cache.CacheBuilderSpec for testing purposes + +package com.google.common.cache; + + +public class CacheBuilderSpec +{ + protected CacheBuilderSpec() {} + public String toParsableString(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static CacheBuilderSpec disableCaching(){ return null; } + public static CacheBuilderSpec parse(String p0){ return null; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheLoader.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheLoader.java new file mode 100644 index 00000000000..00b9bfaad7d --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/CacheLoader.java @@ -0,0 +1,20 @@ +// Generated automatically from com.google.common.cache.CacheLoader for testing purposes + +package com.google.common.cache; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Map; +import java.util.concurrent.Executor; + +abstract public class CacheLoader +{ + protected CacheLoader(){} + public ListenableFuture reload(K p0, V p1){ return null; } + public Map loadAll(Iterable p0){ return null; } + public abstract V load(K p0); + public static CacheLoader asyncReloading(CacheLoader p0, Executor p1){ return null; } + public static CacheLoader from(Function p0){ return null; } + public static CacheLoader from(Supplier p0){ return null; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalCause.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalCause.java new file mode 100644 index 00000000000..e179e876b04 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalCause.java @@ -0,0 +1,10 @@ +// Generated automatically from com.google.common.cache.RemovalCause for testing purposes, and adjusted manually + +package com.google.common.cache; + + +public enum RemovalCause +{ + COLLECTED, EXPIRED, EXPLICIT, REPLACED, SIZE; + private RemovalCause() {} +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalListener.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalListener.java new file mode 100644 index 00000000000..5c2dd0fe6e2 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalListener.java @@ -0,0 +1,10 @@ +// Generated automatically from com.google.common.cache.RemovalListener for testing purposes + +package com.google.common.cache; + +import com.google.common.cache.RemovalNotification; + +public interface RemovalListener +{ + void onRemoval(RemovalNotification p0); +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalNotification.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalNotification.java new file mode 100644 index 00000000000..f3ff204aec3 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/RemovalNotification.java @@ -0,0 +1,14 @@ +// Generated automatically from com.google.common.cache.RemovalNotification for testing purposes, and adjusted manually + +package com.google.common.cache; + +import com.google.common.cache.RemovalCause; +import java.util.AbstractMap; + +public class RemovalNotification extends AbstractMap.SimpleImmutableEntry +{ + protected RemovalNotification(K k, V v) { super(k,v); } + public RemovalCause getCause(){ return null; } + public boolean wasEvicted(){ return false; } + public static RemovalNotification create(K p0, V p1, RemovalCause p2){ return null; } +} diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/cache/Weigher.java b/java/ql/test/stubs/guava-30.0/com/google/common/cache/Weigher.java new file mode 100644 index 00000000000..3e6e0d61e22 --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/cache/Weigher.java @@ -0,0 +1,9 @@ +// Generated automatically from com.google.common.cache.Weigher for testing purposes + +package com.google.common.cache; + + +public interface Weigher +{ + int weigh(K p0, V p1); +} 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 index e670680077c..ce39e44126c 100644 --- 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 @@ -5,23 +5,11 @@ package com.google.common.collect; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import java.util.Collection; -import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.Spliterator; abstract class AbstractMultimap implements Multimap { - AbstractMultimap(){} - Iterator valueIterator(){ return null; } - Spliterator> entrySpliterator(){ return null; } - Spliterator valueSpliterator(){ return null; } - abstract Collection> createEntries(); - abstract Collection createValues(); - abstract Iterator> entryIterator(); - abstract Map> createAsMap(); - abstract Multiset createKeys(); - abstract Set createKeySet(); public Collection> entries(){ return null; } public Collection replaceValues(K p0, Iterable p1){ return null; } public Collection values(){ return null; } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java index 5fba2033c73..9dd8e0b6bfe 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/BaseImmutableMultimap.java @@ -6,5 +6,4 @@ import com.google.common.collect.AbstractMultimap; abstract class BaseImmutableMultimap extends AbstractMultimap { - BaseImmutableMultimap(){} } 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 index dc3c1ebfc9c..5bafe704112 100644 --- 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 @@ -13,24 +13,14 @@ import java.util.function.Predicate; abstract public class ImmutableCollection extends AbstractCollection implements Serializable { - ImmutableCollection(){} - Object writeReplace(){ return null; } - Object[] internalArray(){ return null; } - abstract boolean isPartialView(); abstract static public class Builder { - Builder(){} public ImmutableCollection.Builder add(E... p0){ return null; } public ImmutableCollection.Builder addAll(Iterable p0){ return null; } public ImmutableCollection.Builder addAll(Iterator p0){ return null; } public abstract ImmutableCollection.Builder add(E p0); public abstract ImmutableCollection build(); - static int DEFAULT_INITIAL_CAPACITY = 0; - static int expandedCapacity(int p0, int p1){ return 0; } } - int copyIntoArray(Object[] p0, int p1){ return 0; } - int internalArrayEnd(){ return 0; } - int internalArrayStart(){ return 0; } public ImmutableList asList(){ return null; } public Spliterator spliterator(){ return null; } public abstract UnmodifiableIterator iterator(); @@ -44,5 +34,4 @@ abstract public class ImmutableCollection extends AbstractCollection imple public final boolean removeIf(Predicate p0){ return false; } public final boolean retainAll(Collection p0){ return false; } public final void clear(){} - static int SPLITERATOR_CHARACTERISTICS = 0; } 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 index 2252c3b692d..5046e1fd2af 100644 --- 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 @@ -17,10 +17,6 @@ import java.util.stream.Collector; abstract public class ImmutableList extends ImmutableCollection implements List, RandomAccess { - ImmutableList(){} - ImmutableList subListUnchecked(int p0, int p1){ return null; } - Object writeReplace(){ return null; } - int copyIntoArray(Object[] p0, int p1){ return 0; } public ImmutableList reverse(){ return null; } public ImmutableList subList(int p0, int p1){ return null; } public Spliterator spliterator(){ return null; } @@ -62,13 +58,8 @@ abstract public class ImmutableList extends ImmutableCollection implements public static ImmutableList of(E p0, E p1, E p2, E p3, E p4, E p5, E p6, E p7, E p8, E p9, E p10, E p11, E... p12){ return null; } public static ImmutableList sortedCopyOf(Comparator p0, Iterable p1){ return null; } public void forEach(Consumer p0){} - static ImmutableList asImmutableList(Object[] p0){ return null; } - static ImmutableList asImmutableList(Object[] p0, int p1){ return null; } static public class Builder extends ImmutableCollection.Builder { - Builder(int p0){} - ImmutableList.Builder combine(ImmutableList.Builder p0){ return null; } - Object[] contents = null; public Builder(){} public ImmutableList.Builder add(E p0){ return null; } public ImmutableList.Builder add(E... p0){ 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 index cae21e11cc5..b4617bb5d1c 100644 --- 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 @@ -5,11 +5,9 @@ package com.google.common.collect; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; -import com.google.common.collect.UnmodifiableIterator; import java.io.Serializable; import java.util.Comparator; import java.util.Map; -import java.util.Spliterator; import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Function; @@ -17,15 +15,6 @@ import java.util.stream.Collector; abstract public class ImmutableMap implements Map, Serializable { - ImmutableMap(){} - Object writeReplace(){ return null; } - Spliterator keySpliterator(){ return null; } - UnmodifiableIterator keyIterator(){ return null; } - abstract ImmutableCollection createValues(); - abstract ImmutableSet createKeySet(); - abstract ImmutableSet> createEntrySet(); - abstract boolean isPartialView(); - boolean isHashCodeFast(){ return false; } public ImmutableCollection values(){ return null; } public ImmutableSet keySet(){ return null; } public ImmutableSet> entrySet(){ return null; } @@ -63,18 +52,8 @@ abstract public class ImmutableMap implements Map, Serializable public static ImmutableMap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7, K p8, V p9){ return null; } public static Collector> toImmutableMap(Function p0, Function p1){ return null; } public static Collector> toImmutableMap(Function p0, Function p1, BinaryOperator p2){ return null; } - static Map.Entry entryOf(K p0, V p1){ return null; } - static IllegalArgumentException conflictException(String p0, Object p1, Object p2){ return null; } - static Map.Entry[] EMPTY_ENTRY_ARRAY = null; static public class Builder { - Builder(int p0){} - Comparator valueComparator = null; - ImmutableMap.Builder combine(ImmutableMap.Builder p0){ return null; } - ImmutableMap buildJdkBacked(){ return null; } - Map.Entry[] entries = null; - boolean entriesUsed = false; - int size = 0; public Builder(){} public ImmutableMap.Builder orderEntriesByValue(Comparator p0){ return null; } public ImmutableMap.Builder put(K p0, V p1){ return null; } @@ -83,5 +62,4 @@ abstract public class ImmutableMap implements Map, Serializable public ImmutableMap.Builder putAll(Map p0){ return null; } public ImmutableMap build(){ return null; } } - static void checkNoConflict(boolean p0, String p1, Map.Entry p2, Map.Entry p3){} } 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 index 8e00b81f81d..2eaed07d598 100644 --- 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 @@ -8,30 +8,15 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; -import com.google.common.collect.UnmodifiableIterator; import java.io.Serializable; import java.util.Collection; import java.util.Comparator; import java.util.Map; -import java.util.Set; -import java.util.Spliterator; import java.util.function.BiConsumer; abstract public class ImmutableMultimap extends BaseImmutableMultimap implements Serializable { protected ImmutableMultimap() {} - ImmutableCollection> createEntries(){ return null; } - ImmutableCollection createValues(){ return null; } - ImmutableMultimap(ImmutableMap> p0, int p1){} - ImmutableMultiset createKeys(){ return null; } - Map> createAsMap(){ return null; } - Set createKeySet(){ return null; } - Spliterator> entrySpliterator(){ return null; } - UnmodifiableIterator> entryIterator(){ return null; } - UnmodifiableIterator valueIterator(){ return null; } - boolean isPartialView(){ return false; } - final ImmutableMap> map = null; - final int size = 0; public ImmutableCollection> entries(){ return null; } public ImmutableCollection removeAll(Object p0){ return null; } public ImmutableCollection replaceValues(K p0, Iterable p1){ return null; } @@ -61,11 +46,6 @@ abstract public class ImmutableMultimap extends BaseImmutableMultimap p0){} static public class Builder { - Collection newMutableValueCollection(){ return null; } - Comparator keyComparator = null; - Comparator valueComparator = null; - ImmutableMultimap.Builder combine(ImmutableMultimap.Builder p0){ return null; } - Map> builderMap = null; public Builder(){} public ImmutableMultimap.Builder orderKeysBy(Comparator p0){ return null; } public ImmutableMultimap.Builder orderValuesBy(Comparator p0){ return null; } 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 index c78654fdc14..cb6d7422c0b 100644 --- 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 @@ -8,7 +8,6 @@ import com.google.common.collect.ImmutableMultisetGwtSerializationDependencies; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multiset; import com.google.common.collect.UnmodifiableIterator; -import java.util.Collection; import java.util.Iterator; import java.util.function.Function; import java.util.function.ToIntFunction; @@ -16,10 +15,6 @@ import java.util.stream.Collector; abstract public class ImmutableMultiset extends ImmutableMultisetGwtSerializationDependencies implements Multiset { - ImmutableMultiset(){} - Object writeReplace(){ return null; } - abstract Multiset.Entry getEntry(int p0); - int copyIntoArray(Object[] p0, int p1){ return 0; } public ImmutableList asList(){ return null; } public ImmutableSet> entrySet(){ return null; } public String toString(){ return null; } @@ -45,12 +40,8 @@ abstract public class ImmutableMultiset extends ImmutableMultisetGwtSerializa public static ImmutableMultiset of(E p0, E p1, E p2, E p3, E p4){ return null; } public static ImmutableMultiset of(E p0, E p1, E p2, E p3, E p4, E p5, E... p6){ return null; } public static Collector> toImmutableMultiset(Function p0, ToIntFunction p1){ return null; } - static ImmutableMultiset copyFromEntries(Collection> p0){ return null; } static public class Builder extends ImmutableCollection.Builder { - Builder(Multiset p0){} - ImmutableMultiset buildJdkBacked(){ return null; } - final Multiset contents = null; public Builder(){} public ImmutableMultiset.Builder add(E p0){ return null; } public ImmutableMultiset.Builder add(E... p0){ return null; } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java index b489a250e27..5f1c6da591a 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableMultisetGwtSerializationDependencies.java @@ -6,5 +6,4 @@ import com.google.common.collect.ImmutableCollection; abstract class ImmutableMultisetGwtSerializationDependencies extends ImmutableCollection { - ImmutableMultisetGwtSerializationDependencies(){} } 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 index a277e287390..9f1301f595a 100644 --- 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 @@ -12,10 +12,6 @@ import java.util.stream.Collector; abstract public class ImmutableSet extends ImmutableCollection implements Set { - ImmutableList createAsList(){ return null; } - ImmutableSet(){} - Object writeReplace(){ return null; } - boolean isHashCodeFast(){ return false; } public ImmutableList asList(){ return null; } public abstract UnmodifiableIterator iterator(); public boolean equals(Object p0){ return false; } @@ -34,27 +30,13 @@ abstract public class ImmutableSet extends ImmutableCollection implements public static ImmutableSet of(E p0, E p1, E p2, E p3){ return null; } public static ImmutableSet of(E p0, E p1, E p2, E p3, E p4){ return null; } public static ImmutableSet of(E p0, E p1, E p2, E p3, E p4, E p5, E... p6){ return null; } - static Object[] rebuildHashTable(int p0, Object[] p1, int p2){ return null; } - static boolean hashFloodingDetected(Object[] p0){ return false; } - static double HASH_FLOODING_FPP = 0; - static int MAX_RUN_MULTIPLIER = 0; - static int MAX_TABLE_SIZE = 0; - static int SPLITERATOR_CHARACTERISTICS = 0; - static int chooseTableSize(int p0){ return 0; } static public class Builder extends ImmutableCollection.Builder { - Builder(boolean p0){} - Builder(int p0){} - ImmutableSet.Builder combine(ImmutableSet.Builder p0){ return null; } - boolean forceCopy = false; - final void copyIfNecessary(){} public Builder(){} public ImmutableSet.Builder add(E p0){ return null; } public ImmutableSet.Builder add(E... p0){ return null; } public ImmutableSet.Builder addAll(Iterable p0){ return null; } public ImmutableSet.Builder addAll(Iterator p0){ return null; } public ImmutableSet build(){ return null; } - void copy(){} - void forceJdk(){} } } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java index daad9655c43..a9b72d12a21 100644 --- a/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java +++ b/java/ql/test/stubs/guava-30.0/com/google/common/collect/ImmutableSetMultimap.java @@ -2,12 +2,10 @@ package com.google.common.collect; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.common.collect.SetMultimap; -import java.util.Collection; import java.util.Comparator; import java.util.Map; import java.util.function.Function; @@ -17,8 +15,6 @@ import java.util.stream.Stream; public class ImmutableSetMultimap extends ImmutableMultimap implements SetMultimap { protected ImmutableSetMultimap() {} - Comparator valueComparator(){ return null; } - ImmutableSetMultimap(ImmutableMap> p0, int p1, Comparator p2){} public ImmutableSet> entries(){ return null; } public ImmutableSet get(K p0){ return null; } public ImmutableSetMultimap inverse(){ return null; } @@ -35,11 +31,8 @@ public class ImmutableSetMultimap extends ImmutableMultimap implemen public static ImmutableSetMultimap of(K p0, V p1, K p2, V p3, K p4, V p5, K p6, V p7, K p8, V p9){ return null; } public static Collector> flatteningToImmutableSetMultimap(Function p0, Function> p1){ return null; } public static Collector> toImmutableSetMultimap(Function p0, Function p1){ return null; } - static ImmutableSetMultimap fromMapEntries(Collection>> p0, Comparator p1){ return null; } static public class Builder extends ImmutableMultimap.Builder { - Collection newMutableValueCollection(){ return null; } - ImmutableSetMultimap.Builder combine(ImmutableMultimap.Builder p0){ return null; } public Builder(){} public ImmutableSetMultimap.Builder orderKeysBy(Comparator p0){ return null; } public ImmutableSetMultimap.Builder orderValuesBy(Comparator p0){ return null; } diff --git a/java/ql/test/stubs/guava-30.0/com/google/common/util/concurrent/ListenableFuture.java b/java/ql/test/stubs/guava-30.0/com/google/common/util/concurrent/ListenableFuture.java new file mode 100644 index 00000000000..3b7844a8a0e --- /dev/null +++ b/java/ql/test/stubs/guava-30.0/com/google/common/util/concurrent/ListenableFuture.java @@ -0,0 +1,11 @@ +// Generated automatically from com.google.common.util.concurrent.ListenableFuture for testing purposes + +package com.google.common.util.concurrent; + +import java.util.concurrent.Executor; +import java.util.concurrent.Future; + +public interface ListenableFuture extends Future +{ + void addListener(Runnable p0, Executor p1); +} From e23f666f6700165693e2b5f86e2075fc62930636 Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 29 Jul 2021 16:39:50 +0100 Subject: [PATCH 133/429] Replace get and newWith methods with real implementations --- .../guava/generated/cache/Test.java | 80 +++++++++++++------ .../frameworks/guava/generated/cache/test.ql | 14 ---- 2 files changed, 54 insertions(+), 40 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java index 877c886f66a..ea3995a6ad1 100644 --- a/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java @@ -2,19 +2,47 @@ package generatedtest; import com.google.common.cache.Cache; import com.google.common.cache.LoadingCache; +import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableMap; import java.util.Map; import java.util.concurrent.ConcurrentMap; +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; // Test case generated by GenerateFlowTestCase.ql public class Test { - Object getMapKey(Object container) { return null; } - Object getMapValue(Object container) { return null; } - Object newWithElement(Object element) { return null; } - Object newWithMapKey(Object element) { return null; } - Object newWithMapValue(Object element) { return null; } - Object source() { return null; } + K getMapKey(Map container) { return container.keySet().iterator().next(); } + K getMapKey(Cache container) { return getMapKey(container.asMap()); } + V getMapValue(Map container) { return container.values().iterator().next(); } + V getMapValue(Cache container) { return getMapValue(container.asMap()); } + Iterable newWithElement(T element) { + List l = new ArrayList(); + l.add(element); + return l; + } + Map newMapWithMapKey(K element) { + Map m = new HashMap(); + m.put(element, null); + return m; + } + LoadingCache newCacheWithMapKey(K element) { + LoadingCache lc = CacheBuilder.newBuilder().build(null); + lc.put(element, null); + return lc; + } + Map newMapWithMapValue(V element) { + Map m = new HashMap(); + m.put(null, element); + return m; + } + LoadingCache newCacheWithMapValue(V element) { + LoadingCache lc = CacheBuilder.newBuilder().build(null); + lc.put(null, element); + return lc; + } + T source() { return null; } void sink(Object o) { } public void test() throws Exception { @@ -22,98 +50,98 @@ public class Test { { // "com.google.common.cache;Cache;true;asMap;();;MapKey of Argument[-1];MapKey of ReturnValue;value" ConcurrentMap out = null; - LoadingCache in = (LoadingCache)newWithMapKey(source()); + LoadingCache in = newCacheWithMapKey(source()); out = in.asMap(); sink(getMapKey(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;asMap;();;MapKey of Argument[-1];MapKey of ReturnValue;value" ConcurrentMap out = null; - Cache in = (Cache)newWithMapKey(source()); + Cache in = newCacheWithMapKey(source()); out = in.asMap(); sink(getMapKey(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;asMap;();;MapValue of Argument[-1];MapValue of ReturnValue;value" ConcurrentMap out = null; - LoadingCache in = (LoadingCache)newWithMapValue(source()); + LoadingCache in = newCacheWithMapValue(source()); out = in.asMap(); sink(getMapValue(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;asMap;();;MapValue of Argument[-1];MapValue of ReturnValue;value" ConcurrentMap out = null; - Cache in = (Cache)newWithMapValue(source()); + Cache in = newCacheWithMapValue(source()); out = in.asMap(); sink(getMapValue(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value" Object out = null; - Cache in = (Cache)newWithMapValue(source()); + Cache in = newCacheWithMapValue(source()); out = in.get(null, null); sink(out); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" ImmutableMap out = null; - Cache in = (Cache)newWithMapValue(source()); + Cache in = newCacheWithMapValue(source()); out = in.getAllPresent(null); sink(getMapValue(out)); // $ hasValueFlow } { - // "com.google.common.cache;Cache;true;getIfPresent;(Object);;MapValue of Argument[-1];ReturnValue;value" + // "com.google.common.cache;Cache;true;getIfPresent;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - Cache in = (Cache)newWithMapValue(source()); + Cache in = newCacheWithMapValue(source()); out = in.getIfPresent(null); sink(out); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[0];MapKey of Argument[-1];value" Cache out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[1];MapValue of Argument[-1];value" Cache out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getMapValue(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" Cache out = null; - Map in = (Map)newWithMapKey(source()); + Map in = newMapWithMapKey(source()); out.putAll(in); sink(getMapKey(out)); // $ hasValueFlow } { // "com.google.common.cache;Cache;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" Cache out = null; - Map in = (Map)newWithMapValue(source()); + Map in = newMapWithMapValue(source()); out.putAll(in); sink(getMapValue(out)); // $ hasValueFlow } { - // "com.google.common.cache;LoadingCache;true;apply;(Object);;MapValue of Argument[-1];ReturnValue;value" + // "com.google.common.cache;LoadingCache;true;apply;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - LoadingCache in = (LoadingCache)newWithMapValue(source()); + LoadingCache in = newCacheWithMapValue(source()); out = in.apply(null); sink(out); // $ hasValueFlow } { - // "com.google.common.cache;LoadingCache;true;get;(Object);;MapValue of Argument[-1];ReturnValue;value" + // "com.google.common.cache;LoadingCache;true;get;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - LoadingCache in = (LoadingCache)newWithMapValue(source()); + LoadingCache in = newCacheWithMapValue(source()); out = in.get(null); sink(out); // $ hasValueFlow } { // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value" ImmutableMap out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newWithElement(source()); LoadingCache instance = null; out = instance.getAll(in); sink(getMapKey(out)); // $ hasValueFlow @@ -121,14 +149,14 @@ public class Test { { // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" ImmutableMap out = null; - LoadingCache in = (LoadingCache)newWithMapValue(source()); + LoadingCache in = newCacheWithMapValue(source()); out = in.getAll(null); sink(getMapValue(out)); // $ hasValueFlow } { - // "com.google.common.cache;LoadingCache;true;getUnchecked;(Object);;MapValue of Argument[-1];ReturnValue;value" + // "com.google.common.cache;LoadingCache;true;getUnchecked;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - LoadingCache in = (LoadingCache)newWithMapValue(source()); + LoadingCache in = newCacheWithMapValue(source()); out = in.getUnchecked(null); sink(out); // $ hasValueFlow } diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql index f280580a5a7..465161863cc 100644 --- a/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/test.ql @@ -4,20 +4,6 @@ import semmle.code.java.dataflow.ExternalFlow import semmle.code.java.dataflow.TaintTracking import TestUtilities.InlineExpectationsTest -class SummaryModelTest extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", - "generatedtest;Test;false;newWithElement;;;Argument[0];Element of ReturnValue;value", - "generatedtest;Test;false;getMapKey;;;MapKey of Argument[0];ReturnValue;value", - "generatedtest;Test;false;newWithMapKey;;;Argument[0];MapKey of ReturnValue;value", - "generatedtest;Test;false;getMapValue;;;MapValue of Argument[0];ReturnValue;value", - "generatedtest;Test;false;newWithMapValue;;;Argument[0];MapValue of ReturnValue;value" - ] - } -} - class ValueFlowConf extends DataFlow::Configuration { ValueFlowConf() { this = "qltest:valueFlowConf" } From 227818adb4513bba3a25155be8b55d94b16d7ecf Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Thu, 29 Jul 2021 16:41:33 +0100 Subject: [PATCH 134/429] Add change note --- java/change-notes/2021-07-28-guava-cache.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-07-28-guava-cache.md diff --git a/java/change-notes/2021-07-28-guava-cache.md b/java/change-notes/2021-07-28-guava-cache.md new file mode 100644 index 00000000000..21128d7a60a --- /dev/null +++ b/java/change-notes/2021-07-28-guava-cache.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added additional taint steps modeling methods in the Guava cache package (`com.google.common.cache`) \ No newline at end of file From 8df77060ba1f981d874921cd4cb33b42aa830928 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 13 Jul 2021 09:44:31 +0200 Subject: [PATCH 135/429] C#: Remove type args/params from generic type names in extractor --- .../Semmle.Extraction.CSharp/SymbolExtensions.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index c3bc02bf480..9fb8e5bee5c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -485,18 +485,9 @@ namespace Semmle.Extraction.CSharp if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any()) { - trapFile.Write('<'); - trapFile.BuildList( - ",", - namedType.TypeArguments, - p => - { - if (IsReallyBound(namedType)) - { - p.BuildDisplayName(cx, trapFile); - } - }); - trapFile.Write('>'); + var args = string.Join(',', namedType.TypeArguments.Select(ta => ta.MetadataName)); + + cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Found generic type '{namedType.MetadataName}' with type arguments '{args}', skipping type arguments in type name."); } } From 0cfd73c818b37ca1d0f58315532a49f991b8b7ca Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 13 Jul 2021 10:08:21 +0200 Subject: [PATCH 136/429] Adjust QL getName to the extracted undecorated names --- csharp/ql/src/semmle/code/csharp/Generics.qll | 71 ++++++++++++++----- csharp/ql/src/semmle/code/csharp/Type.qll | 55 +++++--------- 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index 77f5249841f..39ea11416ae 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -105,20 +105,28 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { override Location getALocation() { type_location(this, result) } - /** Gets the name of this generic type without the `<...>` brackets. */ - string getNameWithoutBrackets() { - result = getName().prefix(getName().length() - getNumberOfTypeParameters() - 1) - } - - override string toStringWithTypes() { - result = getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">" - } - override UnboundGenericType getUnboundDeclaration() { result = ValueOrRefType.super.getUnboundDeclaration() } final override Type getChild(int n) { result = getTypeParameter(n) } + + private string getTypeParameterCommas() { + result = strictconcat(int i | exists(this.getTypeParameter(i)) | "", ",") + } + + override string toStringWithTypes() { + result = this.getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">" + } + + final override string getName() { + result = this.getNameWithoutBrackets() + "<" + this.getTypeParameterCommas() + ">" + } + + final override predicate hasQualifiedName(string qualifier, string name) { + super.hasQualifiedName(qualifier, _) and + name = this.getNameWithoutBrackets() + "<" + this.getTypeParameterCommas() + ">" + } } /** @@ -360,22 +368,51 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { override UnboundGenericType getUnboundGeneric() { constructed_generic(this, getTypeRef(result)) } - override string toStringWithTypes() { - result = - getUnboundGeneric().getNameWithoutBrackets() + "<" + this.getTypeArgumentsString() + ">" - } - final override Type getChild(int n) { result = getTypeArgument(n) } language[monotonicAggregates] private string getTypeArgumentsString() { result = - concat(int i | - exists(this.getTypeArgument(i)) + strictconcat(Type t, int i | t = this.getTypeArgument(i) | t.toString(), ", " order by i) + } + + language[monotonicAggregates] + private string getTypeArgumentsNames() { + result = + strictconcat(Type t, int i | t = this.getTypeArgument(i) | t.getName(), ", " order by i) + } + + language[monotonicAggregates] + private string getTypeArgumentsQualifiedNames() { + result = + strictconcat(Type t, int i | + t = this.getTypeArgument(i) | - this.getTypeArgument(i).toString(), ", " order by i + t.getQualifiedName(), "," order by i ) } + + final override string toStringWithTypes() { + exists(string undecorated | + types(this, _, undecorated) and + result = undecorated + "<" + this.getTypeArgumentsString() + ">" + ) + } + + final override string getName() { + exists(string undecorated | + types(this, _, undecorated) and + result = undecorated + "<" + this.getTypeArgumentsNames() + ">" + ) + } + + final override predicate hasQualifiedName(string qualifier, string name) { + exists(string undecorated | + super.hasQualifiedName(qualifier, _) and + types(this, _, undecorated) and + name = undecorated + "<" + this.getTypeArgumentsQualifiedNames() + ">" + ) + } } /** diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index eea631ba377..e9ece98c49c 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -55,27 +55,8 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType } * Either a value type (`ValueType`) or a reference type (`RefType`). */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type { - /** Gets the name of this type without `<...>` brackets, in case it is a constructed type. */ - private string getNameWithoutBrackets() { - exists(UnboundGenericType unbound, string name | - unbound = this.(ConstructedType).getUnboundDeclaration() and - name = unbound.getName() and - result = name.prefix(name.length() - unbound.getNumberOfTypeParameters() - 1) - ) - or - not this instanceof ConstructedType and - result = this.getName() - } - - language[monotonicAggregates] - private string getQualifiedTypeArguments() { - result = - strictconcat(Type t, int i | - t = this.(ConstructedType).getTypeArgument(i) - | - t.getQualifiedName(), "," order by i - ) - } + /** Gets the name of this type without `<...>` brackets, in case it is a generic type. */ + string getNameWithoutBrackets() { types(this, _, result) } /** * Holds if this type has the qualified name `qualifier`.`name`. @@ -84,21 +65,14 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * `qualifier`=`System.IO` and `name`=`IOException`. */ override predicate hasQualifiedName(string qualifier, string name) { - exists(string name0 | - not this instanceof ConstructedType and - name = name0 - or - name = name0 + "<" + this.getQualifiedTypeArguments() + ">" - | - exists(string enclosing | - this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and - name0 = enclosing + "+" + this.getNameWithoutBrackets() - ) - or - not exists(this.getDeclaringType()) and - qualifier = this.getNamespace().getQualifiedName() and - name0 = this.getNameWithoutBrackets() + exists(string enclosing | + this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and + name = enclosing + "+" + this.getNameWithoutBrackets() ) + or + not exists(this.getDeclaringType()) and + qualifier = this.getNamespace().getQualifiedName() and + name = this.getNameWithoutBrackets() } /** Gets the namespace containing this type. */ @@ -963,6 +937,15 @@ class NullableType extends ValueType, DotNet::ConstructedGeneric, @nullable_type override Type getTypeArgument(int p) { p = 0 and result = getUnderlyingType() } override string getAPrimaryQlClass() { result = "NullableType" } + + final override string getName() { + result = "Nullable<" + this.getUnderlyingType().getName() + ">" + } + + final override predicate hasQualifiedName(string qualifier, string name) { + qualifier = "System" and + name = "Nullable<" + this.getUnderlyingType().getQualifiedName() + ">" + } } /** @@ -1046,7 +1029,7 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type { override Type getChild(int n) { result = getReferentType() and n = 0 } - override string getName() { result = DotNet::PointerType.super.getName() } + override string getName() { types(this, _, result) } override Location getALocation() { result = getReferentType().getALocation() } From 99fe9d8d07ddceccbd96d8c92f80692a8d93a4aa Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 13 Jul 2021 13:43:02 +0200 Subject: [PATCH 137/429] Fix erroneous space in type name --- csharp/ql/src/semmle/code/csharp/Generics.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index 39ea11416ae..2a98ac191b3 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -378,8 +378,7 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { language[monotonicAggregates] private string getTypeArgumentsNames() { - result = - strictconcat(Type t, int i | t = this.getTypeArgument(i) | t.getName(), ", " order by i) + result = strictconcat(Type t, int i | t = this.getTypeArgument(i) | t.getName(), "," order by i) } language[monotonicAggregates] From d3803b01e426873e819979d2739435d943e5c207 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 13 Jul 2021 14:59:35 +0200 Subject: [PATCH 138/429] Fix nested generic type qualified names --- csharp/ql/src/semmle/code/csharp/Generics.qll | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index 2a98ac191b3..f4e1931babd 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -124,8 +124,16 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { } final override predicate hasQualifiedName(string qualifier, string name) { - super.hasQualifiedName(qualifier, _) and - name = this.getNameWithoutBrackets() + "<" + this.getTypeParameterCommas() + ">" + exists(string name0 | name = name0 + "<" + this.getTypeParameterCommas() + ">" | + exists(string enclosing | + this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and + name0 = enclosing + "+" + this.getNameWithoutBrackets() + ) + or + not exists(this.getDeclaringType()) and + qualifier = this.getNamespace().getQualifiedName() and + name0 = this.getNameWithoutBrackets() + ) } } @@ -406,10 +414,15 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { } final override predicate hasQualifiedName(string qualifier, string name) { - exists(string undecorated | - super.hasQualifiedName(qualifier, _) and - types(this, _, undecorated) and - name = undecorated + "<" + this.getTypeArgumentsQualifiedNames() + ">" + exists(string name0 | name = name0 + "<" + this.getTypeArgumentsQualifiedNames() + ">" | + exists(string enclosing | + this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and + name0 = enclosing + "+" + this.getNameWithoutBrackets() + ) + or + not exists(this.getDeclaringType()) and + qualifier = this.getNamespace().getQualifiedName() and + name0 = this.getNameWithoutBrackets() ) } } From 62f5af9ac86bdffd5c4b24c38f62b1a9c74e598f Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 13 Jul 2021 15:23:06 +0200 Subject: [PATCH 139/429] Fix TupleType::getName --- csharp/ql/src/semmle/code/csharp/Type.qll | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index e9ece98c49c..c0261850cc0 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -1103,11 +1103,14 @@ class TupleType extends ValueType, @tuple_type { override string toStringWithTypes() { result = "(" + - concat(int i | - exists(getElement(i)) - | - getElement(i).getType().toStringWithTypes(), ", " order by i - ) + ")" + concat(Type t, int i | t = getElement(i).getType() | t.toStringWithTypes(), ", " order by i) + + ")" + } + + language[monotonicAggregates] + override string getName() { + result = + "(" + concat(Type t, int i | t = getElement(i).getType() | t.getName(), "," order by i) + ")" } override string getLabel() { result = getUnderlyingType().getLabel() } From f1a596ee8110a7c755c9b429dd2290b26c3a901d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 14 Jul 2021 13:54:01 +0200 Subject: [PATCH 140/429] Fix code review findings --- .../SymbolExtensions.cs | 7 ----- csharp/ql/src/definitions.qll | 5 ++-- .../src/semmle/code/csharp/AnnotatedType.qll | 2 +- csharp/ql/src/semmle/code/csharp/Generics.qll | 26 +++++++------------ csharp/ql/src/semmle/code/csharp/Type.qll | 23 +++++++--------- .../csharp/frameworks/system/data/Entity.qll | 4 +-- 6 files changed, 24 insertions(+), 43 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 9fb8e5bee5c..caf45880b83 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -482,13 +482,6 @@ namespace Semmle.Extraction.CSharp { trapFile.Write(TrapExtensions.EncodeString(namedType.Name)); } - - if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any()) - { - var args = string.Join(',', namedType.TypeArguments.Select(ta => ta.MetadataName)); - - cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Found generic type '{namedType.MetadataName}' with type arguments '{args}', skipping type arguments in type name."); - } } public static bool IsReallyUnbound(this INamedTypeSymbol type) => diff --git a/csharp/ql/src/definitions.qll b/csharp/ql/src/definitions.qll index c1b456f4dbf..ade40435e18 100644 --- a/csharp/ql/src/definitions.qll +++ b/csharp/ql/src/definitions.qll @@ -158,11 +158,10 @@ private class TypeMentionUse extends Use, TypeMention { Use.super.hasLocationInfo(filepath, startline, startcolumn, endline, _) and endcolumn = startcolumn + - this.getType().(ConstructedType).getUnboundGeneric().getNameWithoutBrackets().length() - 1 + this.getType().(ConstructedType).getUnboundGeneric().getUndecoratedName().length() - 1 or Use.super.hasLocationInfo(filepath, startline, startcolumn, endline, _) and - endcolumn = - startcolumn + this.getType().(UnboundGenericType).getNameWithoutBrackets().length() - 1 + endcolumn = startcolumn + this.getType().(UnboundGenericType).getUndecoratedName().length() - 1 or not this.getType() instanceof ConstructedType and not this.getType() instanceof UnboundGenericType and diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 6a6274821d7..37aa2b23410 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -407,7 +407,7 @@ class AnnotatedConstructedType extends AnnotatedType { override string toString() { result = - annotations.getTypePrefix() + type.getUnboundGeneric().getNameWithoutBrackets() + "<" + + annotations.getTypePrefix() + type.getUnboundGeneric().getUndecoratedName() + "<" + this.getTypeArgumentsString() + ">" + annotations.getTypeSuffix() } diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index f4e1931babd..251ae723c8a 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -116,23 +116,23 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { } override string toStringWithTypes() { - result = this.getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">" + result = this.getUndecoratedName() + "<" + this.typeParametersToString() + ">" } final override string getName() { - result = this.getNameWithoutBrackets() + "<" + this.getTypeParameterCommas() + ">" + result = this.getUndecoratedName() + "<" + this.getTypeParameterCommas() + ">" } final override predicate hasQualifiedName(string qualifier, string name) { exists(string name0 | name = name0 + "<" + this.getTypeParameterCommas() + ">" | exists(string enclosing | this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and - name0 = enclosing + "+" + this.getNameWithoutBrackets() + name0 = enclosing + "+" + this.getUndecoratedName() ) or not exists(this.getDeclaringType()) and qualifier = this.getNamespace().getQualifiedName() and - name0 = this.getNameWithoutBrackets() + name0 = this.getUndecoratedName() ) } } @@ -348,8 +348,8 @@ class UnboundGenericDelegateType extends DelegateType, UnboundGenericType { override string toStringWithTypes() { result = - getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">(" + - parameterTypesToString() + ")" + getUndecoratedName() + "<" + this.typeParametersToString() + ">(" + parameterTypesToString() + + ")" } } @@ -400,29 +400,23 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { } final override string toStringWithTypes() { - exists(string undecorated | - types(this, _, undecorated) and - result = undecorated + "<" + this.getTypeArgumentsString() + ">" - ) + result = this.getUndecoratedName() + "<" + this.getTypeArgumentsString() + ">" } final override string getName() { - exists(string undecorated | - types(this, _, undecorated) and - result = undecorated + "<" + this.getTypeArgumentsNames() + ">" - ) + result = this.getUndecoratedName() + "<" + this.getTypeArgumentsNames() + ">" } final override predicate hasQualifiedName(string qualifier, string name) { exists(string name0 | name = name0 + "<" + this.getTypeArgumentsQualifiedNames() + ">" | exists(string enclosing | this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and - name0 = enclosing + "+" + this.getNameWithoutBrackets() + name0 = enclosing + "+" + this.getUndecoratedName() ) or not exists(this.getDeclaringType()) and qualifier = this.getNamespace().getQualifiedName() and - name0 = this.getNameWithoutBrackets() + name0 = this.getUndecoratedName() ) } } diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index c0261850cc0..f7f0bf2c7e3 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -55,8 +55,12 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType } * Either a value type (`ValueType`) or a reference type (`RefType`). */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type { - /** Gets the name of this type without `<...>` brackets, in case it is a generic type. */ - string getNameWithoutBrackets() { types(this, _, result) } + /** + * DEPRECATED: use `getUndecoratedName()` instead + * + * Gets the name of this type without `<...>` brackets, in case it is a generic type. + */ + deprecated string getNameWithoutBrackets() { types(this, _, result) } /** * Holds if this type has the qualified name `qualifier`.`name`. @@ -67,12 +71,12 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ override predicate hasQualifiedName(string qualifier, string name) { exists(string enclosing | this.getDeclaringType().hasQualifiedName(qualifier, enclosing) and - name = enclosing + "+" + this.getNameWithoutBrackets() + name = enclosing + "+" + this.getUndecoratedName() ) or not exists(this.getDeclaringType()) and qualifier = this.getNamespace().getQualifiedName() and - name = this.getNameWithoutBrackets() + name = this.getUndecoratedName() } /** Gets the namespace containing this type. */ @@ -86,16 +90,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ override ValueOrRefType getDeclaringType() { none() } - override string getUndecoratedName() { - if this.getName().indexOf("<") > 0 - then - exists(string name, int p | - name = this.getName() and p = min(int p2 | p2 = name.indexOf("<") and p2 > 0) - | - result = name.substring(0, p) - ) - else result = this.getName() - } + override string getUndecoratedName() { types(this, _, result) } /** Gets a nested child type, if any. */ NestedType getAChildType() { nested_types(result, this, _) } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll index e60e73f5113..5109db04af6 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll @@ -39,7 +39,7 @@ module SystemDataEntity { /** The `System.Data.Entity.DbSet` class. */ class DbSet extends Class { DbSet() { - this.getUnboundDeclaration().(csharp::UnboundGenericClass).getNameWithoutBrackets() = "DbSet" + this.getUnboundDeclaration().(csharp::UnboundGenericClass).getUndecoratedName() = "DbSet" } /** Gets the `SqlQuery` method. */ @@ -100,7 +100,7 @@ module SystemDataEntityInfrastructure { this.getABaseType*() .getUnboundDeclaration() .(csharp::UnboundGenericClass) - .getNameWithoutBrackets() = "DbRawSqlQuery" + .getUndecoratedName() = "DbRawSqlQuery" } } } From 6405b8944363b3c38f5e32dfa22bc3cbf37fe1a1 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 14 Jul 2021 14:41:12 +0200 Subject: [PATCH 141/429] Add DB upgrade script to change generic type names to undecorated ones --- csharp/ql/src/semmle/code/csharp/Type.qll | 2 +- csharp/ql/src/semmlecode.csharp.dbscheme | 10 + .../old.dbscheme | 2083 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 2093 +++++++++++++++++ .../types.ql | 27 + .../upgrade.properties | 4 + 6 files changed, 4218 insertions(+), 1 deletion(-) create mode 100644 csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/old.dbscheme create mode 100644 csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/types.ql create mode 100644 csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/upgrade.properties diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index f7f0bf2c7e3..e6eabeafc59 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -56,7 +56,7 @@ private predicate isObjectClass(Class c) { c instanceof ObjectType } */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type { /** - * DEPRECATED: use `getUndecoratedName()` instead + * DEPRECATED: use `getUndecoratedName()` instead. * * Gets the name of this type without `<...>` brackets, in case it is a generic type. */ diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index 770f844243d..0f562410898 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -1,3 +1,13 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ /** * An invocation of the compiler. Note that more than one file may be diff --git a/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/old.dbscheme b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/old.dbscheme new file mode 100644 index 00000000000..770f844243d --- /dev/null +++ b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/old.dbscheme @@ -0,0 +1,2083 @@ + +/** + * 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( + 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 +| 130 = @with_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/770f844243d5a2282861b33fd201d0a02e3528d9/semmlecode.csharp.dbscheme b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..0f562410898 --- /dev/null +++ b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/semmlecode.csharp.dbscheme @@ -0,0 +1,2093 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * 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( + 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 +| 130 = @with_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/770f844243d5a2282861b33fd201d0a02e3528d9/types.ql b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/types.ql new file mode 100644 index 00000000000..151a7ad5907 --- /dev/null +++ b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/types.ql @@ -0,0 +1,27 @@ +class Type extends @type { + string toString() { none() } + + string getNewName() { + not this instanceof Generic and + types(this, _, result) + or + result = this.(Generic).getUndecoratedName() + } +} + +class Generic extends Type { + Generic() { + type_parameters(_, _, this, _) or + type_arguments(_, _, this) + } + + string getUndecoratedName() { + exists(string oldName | + types(this, _, oldName) and result = oldName.prefix(min(int i | i = oldName.indexOf("<"))) + ) + } +} + +from Type type, int kind +where types(type, kind, _) +select type, kind, type.getNewName() diff --git a/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/upgrade.properties b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/upgrade.properties new file mode 100644 index 00000000000..051608334fa --- /dev/null +++ b/csharp/upgrades/770f844243d5a2282861b33fd201d0a02e3528d9/upgrade.properties @@ -0,0 +1,4 @@ +description: Extractor changed to not include angle brackets in generic type names. +compatibility: backwards + +types.rel: run types.qlo \ No newline at end of file From 39ea0a989aa44729e18763075c958b93dcd5c0d2 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 28 Jun 2021 06:38:14 +0100 Subject: [PATCH 142/429] Model *Utils classes --- .../java/frameworks/apache/Collections.qll | 335 +++++++++++++++++- 1 file changed, 333 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index ba71731aae7..7ec222e3b15 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -139,6 +139,7 @@ private class ApacheMapUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = [ + // Note that when lambdas are supported we should have more models for populateMap "org.apache.commons.collections4;MapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", @@ -166,7 +167,6 @@ private class ApacheMapUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections4;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", "org.apache.commons.collections4;MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - // Note that when lambdas are supported we should have more models for populateMap "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", @@ -226,7 +226,6 @@ private class ApacheMapUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", "org.apache.commons.collections;MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - // Note that when lambdas are supported we should have more models for populateMap "org.apache.commons.collections;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", @@ -262,3 +261,335 @@ private class ApacheMapUtilsModel extends SummaryModelCsv { ] } } + +/** + * Value-propagating models for the class `org.apache.commons.collections4.CollectionUtils`. + */ +private class ApacheCollectionUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + // Note that when lambdas are supported we should have a model for collect, forAllButLastDo, forAllDo, transform + "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections4;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value", + "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", + "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", + "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", + "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.ListUtils`. + */ +private class ApacheListUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.IteratorUtils`. + */ +private class ApacheIteratorUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterator + "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of Argument[1];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.IterableUtils`. + */ +private class ApacheIterableUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterable + "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.EnumerationUtils`. + */ +private class ApacheEnumerationUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.MultiMapUtils`. + */ +private class ApacheMultiMapUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.MultiSetUtils`. + */ +private class ApacheMultiSetUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.QueueUtils`. + */ +private class ApacheQueueUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the classes `org.apache.commons.collections4.SetUtils` + * and `org.apache.commons.collections4.SetUtils$SetView`. + */ +private class ApacheSetUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections4;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;hashSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.SplitMapUtils`. + */ +private class ApacheSplitMapUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.TrieUtils`. + */ +private class ApacheTrieUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] + } +} + +/** + * Value-propagating models for the class `org.apache.commons.collections4.BagUtils`. + */ +private class ApacheBagUtilsModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.collections4;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + ] + } +} From b82389088b9d9c13b6e4a8009e4a2d8e4f3b2249 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Jun 2021 15:17:02 +0100 Subject: [PATCH 143/429] Model interfaces in Apache Commons Collections main package --- .../java/frameworks/apache/Collections.qll | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 7ec222e3b15..3839ad1d292 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -37,8 +37,96 @@ private class ApacheCollectionsModel extends SummaryModelCsv { override predicate row(string row) { row = [ + // Note that when lambdas are supported we should model things relating to Closure, Factory, Transformer, FluentIterable.forEach, FluentIterable.transform + "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections4;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value", + "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections4;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", + "org.apache.commons.collections4;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", + "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", + "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections4;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value", + "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value", + "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", + "org.apache.commons.collections4;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections4;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections4;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value", "org.apache.commons.collections;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", "org.apache.commons.collections;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" ] From a538699a0a7970f2956698a39ecc3bb2f5ac1da5 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 12 Jul 2021 10:56:52 +0100 Subject: [PATCH 144/429] Add automatically generated tests --- .../frameworks/apache-collections/Test.java | 2526 ++++++++++++++++- 1 file changed, 2398 insertions(+), 128 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index f043b30399e..bab7c388d1e 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -1,18 +1,63 @@ package generatedtest; +import java.util.Collection; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; import java.util.Map; +import java.util.NavigableSet; +import java.util.Queue; import java.util.ResourceBundle; +import java.util.Set; import java.util.SortedMap; +import java.util.SortedSet; +import java.util.StringTokenizer; import java.util.TreeMap; import java.util.Vector; +import org.apache.commons.collections4.ArrayStack; +import org.apache.commons.collections4.Bag; +import org.apache.commons.collections4.BagUtils; +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.EnumerationUtils; import org.apache.commons.collections4.Factory; +import org.apache.commons.collections4.FluentIterable; +import org.apache.commons.collections4.Get; import org.apache.commons.collections4.IterableMap; import org.apache.commons.collections4.IterableSortedMap; +import org.apache.commons.collections4.IterableUtils; +import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.collections4.KeyValue; +import org.apache.commons.collections4.ListUtils; +import org.apache.commons.collections4.ListValuedMap; +import org.apache.commons.collections4.MapIterator; import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MultiMap; +import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiSet; +import org.apache.commons.collections4.MultiSetUtils; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.OrderedIterator; import org.apache.commons.collections4.OrderedMap; +import org.apache.commons.collections4.OrderedMapIterator; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Put; +import org.apache.commons.collections4.QueueUtils; +import org.apache.commons.collections4.ResettableIterator; +import org.apache.commons.collections4.ResettableListIterator; +import org.apache.commons.collections4.SetUtils; +import org.apache.commons.collections4.SetValuedMap; +import org.apache.commons.collections4.SortedBag; +import org.apache.commons.collections4.SplitMapUtils; import org.apache.commons.collections4.Transformer; +import org.apache.commons.collections4.Trie; +import org.apache.commons.collections4.TrieUtils; +import org.apache.commons.collections4.iterators.BoundedIterator; +import org.apache.commons.collections4.iterators.SkippingIterator; +import org.apache.commons.collections4.iterators.ZippingIterator; import org.apache.commons.collections4.keyvalue.AbstractKeyValue; import org.apache.commons.collections4.keyvalue.AbstractMapEntry; import org.apache.commons.collections4.keyvalue.AbstractMapEntryDecorator; @@ -22,9 +67,11 @@ import org.apache.commons.collections4.keyvalue.TiedMapEntry; import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry; import org.apache.commons.collections4.map.MultiValueMap; -//Test case generated by GenerateFlowTestCase.ql +// Test case generated by GenerateFlowTestCase.ql public class Test { + static Object getArrayElement(Object[] container) { return container[0]; } + static Object getElement(Iterable container) { return container.iterator().next(); } static Object getMapKey(AbstractKeyValue container) { return container.getKey(); } static Object getMapKeyFromEntry(Map.Entry container) { return container.getKey(); } static Object getMapKey(AbstractMapEntryDecorator container) { return container.getKey(); } @@ -98,658 +145,658 @@ public class Test { AbstractKeyValue out = null; Object in = source(); out = new MyAbstractKeyValue(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[1];MapValue of Argument[-1];value" AbstractKeyValue out = null; Object in = source(); out = new MyAbstractKeyValue(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; Object in = source(); out.setKey(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value" MyAbstractKeyValue out = null; Object in = source(); out.mySetKey(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; DefaultKeyValue in = newDKVWithMapValue(source()); out = in.setKey(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; MyAbstractKeyValue in = newMAKVWithMapValue(source()); out = in.mySetKey(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; MyAbstractKeyValue in = newMAKVWithMapValue(source()); out = in.mySetKey((Object)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; Object in = source(); out.setValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value" DefaultKeyValue out = null; Object in = source(); out.setValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value" AbstractMapEntry out = null; Object in = source(); out.setValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value" MyAbstractKeyValue out = null; Object in = source(); out.mySetValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; UnmodifiableMapEntry in = newUMEWithMapValue(source()); out = in.setValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; DefaultKeyValue in = newDKVWithMapValue(source()); out = in.setValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; AbstractMapEntry in = newMAMEWithMapValue(source()); out = in.setValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; AbstractMapEntry in = newMAMEWithMapValue(source()); out = in.setValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; MyAbstractKeyValue in = newMAKVWithMapValue(source()); out = in.mySetValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; MyAbstractKeyValue in = newMAKVWithMapValue(source()); out = in.mySetValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" String out = null; AbstractKeyValue in = newMAKVWithMapKey(source()); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" String out = null; AbstractKeyValue in = newMAKVWithMapValue(source()); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value" AbstractMapEntry out = null; Object in = source(); out = new MyAbstractMapEntry(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[1];MapValue of Argument[-1];value" AbstractMapEntry out = null; Object in = source(); out = new MyAbstractMapEntry(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value" AbstractMapEntryDecorator out = null; Map.Entry in = newMAMEWithMapKey(source()); out = new MyAbstractMapEntryDecorator(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value" AbstractMapEntryDecorator out = null; Map.Entry in = newMAMEWithMapValue(source()); out = new MyAbstractMapEntryDecorator(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map.Entry out = null; MyAbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); out = in.myGetMapEntry(); - sink(getMapKeyFromEntry(out)); // $hasValueFlow + sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value" Map.Entry out = null; MyAbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); out = in.myGetMapEntry(); - sink(getMapValueFromEntry(out)); // $hasValueFlow + sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" String out = null; AbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" String out = null; AbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; Map.Entry in = newMAMEWithMapKey(source()); out = new DefaultKeyValue(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultKeyValue out = null; Map.Entry in = newMAMEWithMapValue(source()); out = new DefaultKeyValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; KeyValue in = newMAKVWithMapKey(source()); out = new DefaultKeyValue(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultKeyValue out = null; KeyValue in = newMAKVWithMapValue(source()); out = new DefaultKeyValue(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; Object in = source(); out = new DefaultKeyValue(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[1];MapValue of Argument[-1];value" DefaultKeyValue out = null; Object in = source(); out = new DefaultKeyValue(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map.Entry out = null; DefaultKeyValue in = newDKVWithMapKey(source()); out = in.toMapEntry(); - sink(getMapKeyFromEntry(out)); // $hasValueFlow + sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value" Map.Entry out = null; DefaultKeyValue in = newDKVWithMapValue(source()); out = in.toMapEntry(); - sink(getMapValueFromEntry(out)); // $hasValueFlow + sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultMapEntry out = null; Map.Entry in = newMAMEWithMapKey(source()); out = new DefaultMapEntry(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultMapEntry out = null; Map.Entry in = newMAMEWithMapValue(source()); out = new DefaultMapEntry(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultMapEntry out = null; KeyValue in = newMAKVWithMapKey(source()); out = new DefaultMapEntry(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultMapEntry out = null; KeyValue in = newMAKVWithMapValue(source()); out = new DefaultMapEntry(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value" DefaultMapEntry out = null; Object in = source(); out = new DefaultMapEntry(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value" DefaultMapEntry out = null; Object in = source(); out = new DefaultMapEntry(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value" TiedMapEntry out = null; Object in = source(); out = new TiedMapEntry(null, in); - sink(getMapKeyFromEntry(out)); // $hasValueFlow + sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value" TiedMapEntry out = null; Map in = newTreeMapWithMapValue(source()); out = new TiedMapEntry(in, null); - sink(getMapValueFromEntry(out)); // $hasValueFlow + sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" UnmodifiableMapEntry out = null; Map.Entry in = newMAMEWithMapKey(source()); out = new UnmodifiableMapEntry(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; Map.Entry in = newMAMEWithMapValue(source()); out = new UnmodifiableMapEntry(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" UnmodifiableMapEntry out = null; KeyValue in = newMAKVWithMapKey(source()); out = new UnmodifiableMapEntry(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; KeyValue in = newMAKVWithMapValue(source()); out = new UnmodifiableMapEntry(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value" UnmodifiableMapEntry out = null; Object in = source(); out = new UnmodifiableMapEntry(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; Object in = source(); out = new UnmodifiableMapEntry(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; TiedMapEntry in = newTMEWithMapKey(source()); out = in.getKey(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; KeyValue in = newMAKVWithMapKey(source()); out = in.getKey(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; AbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); out = in.getKey(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; AbstractKeyValue in = newMAKVWithMapKey(source()); out = in.getKey(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; TiedMapEntry in = newTMEWithMapValue(source()); out = in.getValue(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; KeyValue in = newMAKVWithMapValue(source()); out = in.getValue(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; AbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); out = in.getValue(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; AbstractKeyValue in = newMAKVWithMapValue(source()); out = in.getValue(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" Map out = null; Map in = (Map)source(); out = MapUtils.emptyIfNull(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.fixedSizeMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.fixedSizeMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.fixedSizeSortedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.fixedSizeSortedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getMap;;;Argument[2];ReturnValue;value" Map out = null; Map in = (Map)source(); out = MapUtils.getMap(null, null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value" Map out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getMap(in, null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value" Map out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getMap(in, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getObject;;;Argument[2];ReturnValue;value" Object out = null; Object in = source(); out = MapUtils.getObject(null, null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value" Object out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getObject(in, null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value" Object out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getObject(in, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getString;;;Argument[2];ReturnValue;value" String out = null; String in = (String)source(); out = MapUtils.getString(null, null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value" String out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getString(in, null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value" String out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.getString(in, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapKey of Argument[0];MapValue of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.invertMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapValue of Argument[0];MapKey of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.invertMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.iterableMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.iterableMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableSortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.iterableSortedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableSortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.iterableSortedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.lazyMap(in, (Transformer)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.lazyMap(in, (Factory)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.lazyMap(in, (Transformer)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.lazyMap(in, (Factory)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.lazySortedMap(in, (Transformer)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.lazySortedMap(in, (Factory)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.lazySortedMap(in, (Transformer)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.lazySortedMap(in, (Factory)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.multiValueMap(in, (Factory)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.multiValueMap(in, (Class)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.multiValueMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.multiValueMap(in, (Factory)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.multiValueMap(in, (Class)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.multiValueMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" OrderedMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.orderedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" OrderedMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.orderedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value" Map out = null; Iterable in = newWithElement((String)source()); MapUtils.populateMap(out, in, (Transformer)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // Note it is tricky to get this to compile - the compiler thinks it is ambiguous @@ -758,231 +805,2454 @@ public class Test { MultiMap out = null; Iterable in = newWithElement((String)source()); MapUtils.populateMap(out, in, (Transformer)null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.predicatedMap(in, null, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.predicatedMap(in, null, null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.predicatedSortedMap(in, null, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.predicatedSortedMap(in, null, null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(source()); MapUtils.putAll(out, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(source()); out = MapUtils.putAll(null, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(source()); MapUtils.putAll(out, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(source()); out = MapUtils.putAll(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(newWithArrayElement(source())); MapUtils.putAll(out, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(newWithArrayElement(source())); out = MapUtils.putAll(null, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(newWithArrayElement(source())); MapUtils.putAll(out, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(newWithArrayElement(source())); out = MapUtils.putAll(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(newMAKVWithMapKey(source())); MapUtils.putAll(out, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(newMAKVWithMapKey(source())); out = MapUtils.putAll(null, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; Object[] in = newWithArrayElement(newMAKVWithMapValue(source())); MapUtils.putAll(out, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; Object[] in = newWithArrayElement(newMAKVWithMapValue(source())); out = MapUtils.putAll(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;safeAddToMap;;;Argument[1];MapKey of Argument[0];value" Map out = null; Object in = source(); MapUtils.safeAddToMap(out, in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;safeAddToMap;;;Argument[2];MapValue of Argument[0];value" Map out = null; Object in = source(); MapUtils.safeAddToMap(out, null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.synchronizedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.synchronizedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.synchronizedSortedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.synchronizedSortedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;toMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; ResourceBundle in = newRBWithMapKey(source()); out = MapUtils.toMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;toMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; ResourceBundle in = newRBWithMapValue(source()); out = MapUtils.toMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.transformedMap(in, null, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.transformedMap(in, null, null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.transformedSortedMap(in, null, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.transformedSortedMap(in, null, null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapKey(source()); out = MapUtils.unmodifiableMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; Map in = newTreeMapWithMapValue(source()); out = MapUtils.unmodifiableMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapKey(source()); out = MapUtils.unmodifiableSortedMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; SortedMap in = newTreeMapWithMapValue(source()); out = MapUtils.unmodifiableSortedMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + ArrayStack in = (ArrayStack)newWithElement(source()); + out = in.peek(0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + ArrayStack in = (ArrayStack)newWithElement(source()); + out = in.peek(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + ArrayStack in = (ArrayStack)newWithElement(source()); + out = in.pop(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value" + ArrayStack out = null; + Object in = (Object)source(); + out.push(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value" + Bag out = null; + Object in = (Object)source(); + out.add(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value" + Bag out = null; + Object in = (Object)source(); + out.add(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value" + Set out = null; + Bag in = (Bag)newWithElement(source()); + out = in.uniqueSet(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value" + Bag out = null; + Bag in = (Bag)newWithElement(source()); + out = BagUtils.collectionBag(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value" + Bag out = null; + Bag in = (Bag)newWithElement(source()); + out = BagUtils.predicatedBag(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + SortedBag out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = BagUtils.predicatedSortedBag(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value" + Bag out = null; + Bag in = (Bag)newWithElement(source()); + out = BagUtils.synchronizedBag(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + SortedBag out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = BagUtils.synchronizedSortedBag(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value" + Bag out = null; + Bag in = (Bag)newWithElement(source()); + out = BagUtils.transformingBag(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + SortedBag out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = BagUtils.transformingSortedBag(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value" + Bag out = null; + Bag in = (Bag)newWithElement(source()); + out = BagUtils.unmodifiableBag(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + SortedBag out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = BagUtils.unmodifiableSortedBag(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + BidiMap in = (BidiMap)newWithMapKey(source()); + out = in.getKey(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value" + BidiMap out = null; + BidiMap in = (BidiMap)newWithMapKey(source()); + out = in.inverseBidiMap(); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value" + BidiMap out = null; + BidiMap in = (BidiMap)newWithMapValue(source()); + out = in.inverseBidiMap(); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + BidiMap in = (BidiMap)newWithMapKey(source()); + out = in.removeValue(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value" + Collection out = null; + Enumeration in = (Enumeration)newWithElement(source()); + CollectionUtils.addAll(out, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + CollectionUtils.addAll(out, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value" + Collection out = null; + Iterator in = (Iterator)newWithElement(source()); + CollectionUtils.addAll(out, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value" + Collection out = null; + C[] in = (C[])newWithArrayElement(source()); + CollectionUtils.addAll(out, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value" + Collection out = null; + Object in = (Object)source(); + CollectionUtils.addIgnoreNull(out, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(in, null, null, false); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(in, (Iterable)null, false); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(in, (Iterable)null, (Comparator)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(null, in, null, false); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate((Iterable)null, in, false); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.collate((Iterable)null, in, (Comparator)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.disjunction(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.disjunction(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" + Collection out = null; + Collection in = (Collection)source(); + out = CollectionUtils.emptyIfNull(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.extractSingleton(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.find(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterator in = (Iterator)newWithElement(source()); + out = CollectionUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value" + Map.Entry out = null; + Map in = (Map)newWithMapKey(source()); + out = CollectionUtils.get(in, 0); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value" + Map.Entry out = null; + Map in = (Map)newWithMapValue(source()); + out = CollectionUtils.get(in, 0); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value" + Object out = null; + Object in = (Object)newWithArrayElement(source()); + out = CollectionUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value" + Object out = null; + Object in = (Object)newWithElement(source()); + out = CollectionUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value" + Object out = null; + Object in = (Object)newWithMapKey(source()); + out = CollectionUtils.get(in, 0); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value" + Object out = null; + Object in = (Object)newWithMapValue(source()); + out = CollectionUtils.get(in, 0); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value" + Map out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.getCardinalityMap(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.intersection(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.intersection(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.permutations(in); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.predicatedCollection(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.removeAll(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.removeAll(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.retainAll(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.retainAll(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + CollectionUtils.select(in, null, out, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + CollectionUtils.select(in, null, out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + CollectionUtils.select(in, null, null, out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.select(in, null, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.select(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.select(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + CollectionUtils.selectRejected(in, null, out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.selectRejected(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.selectRejected(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.subtract(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.subtract(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.synchronizedCollection(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.transformingCollection(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.union(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" + Collection out = null; + Iterable in = (Iterable)newWithElement(source()); + out = CollectionUtils.union(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" + Collection out = null; + Collection in = (Collection)newWithElement(source()); + out = CollectionUtils.unmodifiableCollection(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Enumeration in = (Enumeration)newWithElement(source()); + out = EnumerationUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Enumeration in = (Enumeration)newWithElement(source()); + out = EnumerationUtils.toList(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" + List out = null; + StringTokenizer in = (StringTokenizer)source(); + out = EnumerationUtils.toList(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.append((Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = (Iterable)newWithElement(source()); + FluentIterable instance = null; + out = instance.append(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.append(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value" + Enumeration out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.asEnumeration(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.collate(null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.collate(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = (Iterable)newWithElement(source()); + FluentIterable instance = null; + out = instance.collate(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = (Iterable)newWithElement(source()); + FluentIterable instance = null; + out = instance.collate(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value" + Collection out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + in.copyInto(out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.eval(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.filter(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.get(0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.limit(0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.loop(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = FluentIterable.of(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Object in = (Object)source(); + out = FluentIterable.of(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + T[] in = (T[])newWithArrayElement(source()); + out = FluentIterable.of(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.reverse(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.skip(0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value" + List out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.toList(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint" + String out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.unique(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.unmodifiable(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = (FluentIterable)newWithElement(source()); + out = in.zip((Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = (Iterable)newWithElement(source()); + FluentIterable instance = null; + out = instance.zip(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" + Set out = null; + Get in = (Get)newWithMapKey(source()); + out = in.entrySet(); + sink(getMapKey(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value" + Set out = null; + Get in = (Get)newWithMapValue(source()); + out = in.entrySet(); + sink(getMapValue(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MultiMap in = (MultiMap)newWithMapValue(source()); + out = in.get(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + Get in = (Get)newWithMapValue(source()); + out = in.get(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" + Set out = null; + Get in = (Get)newWithMapKey(source()); + out = in.keySet(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MultiMap in = (MultiMap)newWithMapValue(source()); + out = in.remove(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + Get in = (Get)newWithMapValue(source()); + out = in.remove(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" + Set out = null; + BidiMap in = (BidiMap)newWithMapValue(source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiMap in = (MultiMap)newWithMapValue(source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + Get in = (Get)newWithMapValue(source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" + MapIterator out = null; + IterableGet in = (IterableGet)newWithMapKey(source()); + out = in.mapIterator(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value" + MapIterator out = null; + IterableGet in = (IterableGet)newWithMapValue(source()); + out = in.mapIterator(); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.boundedIterable(in, 0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(in, null, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.chainedIterable(null, null, null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.collatedIterable(null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.collatedIterable(null, null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.collatedIterable(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.collatedIterable(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)source(); + out = IterableUtils.emptyIfNull(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.filteredIterable(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.find(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.first(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.loopingIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.partition(in, null, null); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.partition(in, (Predicate[])null); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.partition(in, (Predicate)null); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.reversedIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.skippingIterable(in, 0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.toList(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.toString(in, null, null, null, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.toString(in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.toString(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.uniqueIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.unmodifiableIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.zippingIterable((Iterable)null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.zippingIterable(in, (Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = (Iterable)newWithElement(source()); + out = IterableUtils.zippingIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayIterator(in, 0, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayIterator(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayListIterator(in, 0, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayListIterator(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.arrayListIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value" + Enumeration out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.asEnumeration(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.asIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Enumeration in = (Enumeration)newWithElement(source()); + out = IteratorUtils.asIterator(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Enumeration in = (Enumeration)newWithElement(source()); + out = IteratorUtils.asIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.asMultipleUseIterable(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value" + BoundedIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.boundedIterator(in, 0L, 0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value" + BoundedIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.boundedIterator(in, 0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Collection in = (Collection)newWithElement(newWithElement(source())); + out = IteratorUtils.chainedIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.chainedIterator(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.chainedIterator(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value" + Iterator out = null; + Collection in = (Collection)newWithElement(newWithElement(source())); + out = IteratorUtils.collatedIterator((Comparator)null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.collatedIterator(null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.collatedIterator(null, null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.filteredIterator(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value" + ListIterator out = null; + ListIterator in = (ListIterator)newWithElement(source()); + out = IteratorUtils.filteredListIterator(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.find(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.first(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.get(in, 0); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value" + Iterator out = null; + Object in = (Object)source(); + out = IteratorUtils.getIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Object in = (Object)newWithArrayElement(source()); + out = IteratorUtils.getIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Object in = (Object)newWithElement(source()); + out = IteratorUtils.getIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Object in = (Object)newWithMapValue(source()); + out = IteratorUtils.getIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Collection in = (Collection)newWithElement(source()); + out = IteratorUtils.loopingIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + List in = (List)newWithElement(source()); + out = IteratorUtils.loopingListIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.peekingIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.pushbackIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object in = (Object)source(); + out = IteratorUtils.singletonIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value" + ListIterator out = null; + Object in = (Object)source(); + out = IteratorUtils.singletonListIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value" + SkippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.skippingIterator(in, 0L); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value" + Object[] out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.toArray(in); + sink(getArrayElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value" + List out = null; + Iterator in = (Iterator)source(); + out = IteratorUtils.toList(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value" + List out = null; + Iterator in = (Iterator)source(); + out = IteratorUtils.toList(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value" + ListIterator out = null; + Iterator in = (Iterator)source(); + out = IteratorUtils.toListIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.toString(in, null, null, null, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.toString(in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" + String out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.toString(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.unmodifiableIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value" + ListIterator out = null; + ListIterator in = (ListIterator)newWithElement(source()); + out = IteratorUtils.unmodifiableListIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value" + MapIterator out = null; + MapIterator in = (MapIterator)newWithElement(source()); + out = IteratorUtils.unmodifiableMapIterator(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value" + MapIterator out = null; + MapIterator in = (MapIterator)newWithMapValue(source()); + out = IteratorUtils.unmodifiableMapIterator(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.zippingIterator(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.zippingIterator(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.zippingIterator(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.zippingIterator(null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = (Iterator)newWithElement(source()); + out = IteratorUtils.zippingIterator(null, null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value" + List out = null; + List in = (List)source(); + out = ListUtils.defaultIfNull(null, in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" + List out = null; + List in = (List)source(); + out = ListUtils.emptyIfNull(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.intersection(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.intersection(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.lazyList(in, (Transformer)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.lazyList(in, (Factory)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint" + String out = null; + CharSequence in = (CharSequence)source(); + out = ListUtils.longestCommonSubsequence(in, (CharSequence)null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint" + String out = null; + CharSequence in = (CharSequence)source(); + out = ListUtils.longestCommonSubsequence((CharSequence)null, in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.longestCommonSubsequence(in, (List)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.longestCommonSubsequence((List)null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.longestCommonSubsequence(in, null, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.longestCommonSubsequence(null, in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.partition(in, 0); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.predicatedList(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Collection in = (Collection)newWithElement(source()); + out = ListUtils.removeAll(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Collection in = (Collection)newWithElement(source()); + out = ListUtils.retainAll(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Collection in = (Collection)newWithElement(source()); + out = ListUtils.select(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + Collection in = (Collection)newWithElement(source()); + out = ListUtils.selectRejected(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.subtract(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.sum(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.sum(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.synchronizedList(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.transformedList(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.union(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.union(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newWithElement(source()); + out = ListUtils.unmodifiableList(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + MapIterator in = (MapIterator)newWithElement(source()); + out = in.getKey(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MapIterator in = (MapIterator)newWithMapValue(source()); + out = in.getValue(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + MapIterator in = (MapIterator)newWithElement(source()); + out = in.next(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value" + MapIterator out = null; + Object in = (Object)source(); + out.setValue(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MapIterator in = (MapIterator)newWithMapValue(source()); + out = in.setValue(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Object out = null; + MultiMap in = (MultiMap)newWithMapValue(newWithElement(source())); + out = in.get(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value" + MultiMap out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" + MultiMap out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiMap in = (MultiMap)newWithMapValue(newWithElement(source())); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)source(); + out = MultiMapUtils.emptyIfNull(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value" + Collection out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.getCollection(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value" + Bag out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.getValuesAsBag(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value" + List out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.getValuesAsList(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value" + Set out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.getValuesAsSet(in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = MultiMapUtils.transformedMultiValuedMap(in, null, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.transformedMultiValuedMap(in, null, null); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = MultiMapUtils.unmodifiableMultiValuedMap(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + out = MultiMapUtils.unmodifiableMultiValuedMap(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + MultiSet.Entry in = (MultiSet.Entry)newWithElement(source()); + out = in.getElement(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value" + MultiSet out = null; + Object in = (Object)source(); + out.add(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value" + MultiSet out = null; + Object in = (Object)source(); + out.add(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value" + Set out = null; + MultiSet in = (MultiSet)newWithElement(source()); + out = in.entrySet(); + sink(getElement(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value" + Set out = null; + MultiSet in = (MultiSet)newWithElement(source()); + out = in.uniqueSet(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + MultiSet out = null; + MultiSet in = (MultiSet)newWithElement(source()); + out = MultiSetUtils.predicatedMultiSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + MultiSet out = null; + MultiSet in = (MultiSet)newWithElement(source()); + out = MultiSetUtils.synchronizedMultiSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + MultiSet out = null; + MultiSet in = (MultiSet)newWithElement(source()); + out = MultiSetUtils.unmodifiableMultiSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value" + Map out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + out = in.asMap(); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" + Map out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = in.asMap(); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Set out = null; + SetValuedMap in = (SetValuedMap)newWithMapValue(newWithElement(source())); + out = in.get(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + List out = null; + ListValuedMap in = (ListValuedMap)newWithMapValue(newWithElement(source())); + out = in.get(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + out = in.get(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value" + Set out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = in.keySet(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value" + MultiSet out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = in.keys(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value" + MapIterator out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + out = in.mapIterator(); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" + MapIterator out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out = in.mapIterator(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value" + MultiValuedMap out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" + MultiValuedMap out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" + MultiValuedMap out = null; + Map in = (Map)newWithMapKey(source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value" + MultiValuedMap out = null; + Map in = (Map)newWithMapValue(source()); + out.putAll(in); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + out.putAll(in); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value" + MultiValuedMap out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value" + MultiValuedMap out = null; + Object in = (Object)source(); + out.putAll(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value" + MultiValuedMap out = null; + Iterable in = (Iterable)newWithElement(source()); + out.putAll(null, in); + sink(getElement(getMapValue(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + OrderedMapIterator in = (OrderedMapIterator)newWithElement(source()); + out = in.previous(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + OrderedIterator in = (OrderedIterator)newWithElement(source()); + out = in.previous(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + OrderedMap in = (OrderedMap)newWithMapKey(source()); + out = in.firstKey(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + OrderedMap in = (OrderedMap)newWithMapKey(source()); + out = in.lastKey(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + OrderedMap in = (OrderedMap)newWithMapKey(source()); + out = in.nextKey(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value" + Object out = null; + OrderedMap in = (OrderedMap)newWithMapKey(source()); + out = in.previousKey(null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" + Put out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" + MultiMap out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" + BidiMap out = null; + Object in = (Object)source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" + Put out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" + MultiMap out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" + BidiMap out = null; + Object in = (Object)source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + Put in = (Put)newWithMapValue(source()); + out = in.put(null, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MultiMap in = (MultiMap)newWithMapValue(source()); + out = in.put(null, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + BidiMap in = (BidiMap)newWithMapValue(source()); + out = in.put(null, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" + Put out = null; + Map in = (Map)newWithMapKey(source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" + Put out = null; + Map in = (Map)newWithMapValue(source()); + out.putAll(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value" + Queue out = null; + Queue in = (Queue)newWithElement(source()); + out = QueueUtils.predicatedQueue(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value" + Queue out = null; + Queue in = (Queue)newWithElement(source()); + out = QueueUtils.synchronizedQueue(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value" + Queue out = null; + Queue in = (Queue)newWithElement(source()); + out = QueueUtils.transformingQueue(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" + Queue out = null; + Queue in = (Queue)newWithElement(source()); + out = QueueUtils.unmodifiableQueue(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value" + Set out = null; + SetUtils.SetView in = (SetUtils.SetView)newWithElement(source()); + in.copyInto(out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value" + Iterator out = null; + SetUtils.SetView in = (SetUtils.SetView)newWithElement(source()); + out = in.createIterator(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.difference(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.difference(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value" + Set out = null; + Set in = (Set)source(); + out = SetUtils.emptyIfNull(in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.intersection(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.intersection(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value" + Set out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.orderedSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + NavigableSet in = (NavigableSet)newWithElement(source()); + out = SetUtils.predicatedNavigableSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value" + Set out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.predicatedSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + SortedSet in = (SortedSet)newWithElement(source()); + out = SetUtils.predicatedSortedSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value" + Set out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.synchronizedSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + SortedSet in = (SortedSet)newWithElement(source()); + out = SetUtils.synchronizedSortedSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + NavigableSet in = (NavigableSet)newWithElement(source()); + out = SetUtils.transformedNavigableSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value" + Set out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.transformedSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + SortedSet in = (SortedSet)newWithElement(source()); + out = SetUtils.transformedSortedSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.union(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.union(null, in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + NavigableSet in = (NavigableSet)newWithElement(source()); + out = SetUtils.unmodifiableNavigableSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value" + Set out = null; + Set in = (Set)newWithElement(source()); + out = SetUtils.unmodifiableSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + SortedSet out = null; + SortedSet in = (SortedSet)newWithElement(source()); + out = SetUtils.unmodifiableSortedSet(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = in.first(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value" + Object out = null; + SortedBag in = (SortedBag)newWithElement(source()); + out = in.last(); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" + IterableMap out = null; + Get in = (Get)newWithMapKey(source()); + out = SplitMapUtils.readableMap(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + IterableMap out = null; + Get in = (Get)newWithMapValue(source()); + out = SplitMapUtils.readableMap(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" + Map out = null; + Put in = (Put)newWithMapKey(source()); + out = SplitMapUtils.writableMap(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + Map out = null; + Put in = (Put)newWithMapValue(source()); + out = SplitMapUtils.writableMap(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" + SortedMap out = null; + Trie in = (Trie)newWithMapKey(source()); + out = in.prefixMap(null); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value" + SortedMap out = null; + Trie in = (Trie)newWithMapValue(source()); + out = in.prefixMap(null); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value" + Trie out = null; + Trie in = (Trie)newWithMapKey(source()); + out = TrieUtils.unmodifiableTrie(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" + Trie out = null; + Trie in = (Trie)newWithMapValue(source()); + out = TrieUtils.unmodifiableTrie(in); + sink(getMapValue(out)); // $ hasValueFlow } } From 2e04319d9f0659d943e5402a120c227c6241e265 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 12 Jul 2021 11:10:56 +0100 Subject: [PATCH 145/429] Manually improve tests --- .../frameworks/apache-collections/Test.java | 906 +++++++++--------- .../frameworks/apache-collections/test.ql | 3 + 2 files changed, 482 insertions(+), 427 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index bab7c388d1e..20606fa9a71 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -3,8 +3,8 @@ package generatedtest; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; -import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -16,6 +16,7 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.StringTokenizer; import java.util.TreeMap; +import java.util.TreeSet; import java.util.Vector; import org.apache.commons.collections4.ArrayStack; import org.apache.commons.collections4.Bag; @@ -26,6 +27,7 @@ import org.apache.commons.collections4.EnumerationUtils; import org.apache.commons.collections4.Factory; import org.apache.commons.collections4.FluentIterable; import org.apache.commons.collections4.Get; +import org.apache.commons.collections4.IterableGet; import org.apache.commons.collections4.IterableMap; import org.apache.commons.collections4.IterableSortedMap; import org.apache.commons.collections4.IterableUtils; @@ -55,7 +57,10 @@ import org.apache.commons.collections4.SplitMapUtils; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.Trie; import org.apache.commons.collections4.TrieUtils; +import org.apache.commons.collections4.bag.TreeBag; +import org.apache.commons.collections4.bidimap.TreeBidiMap; import org.apache.commons.collections4.iterators.BoundedIterator; +import org.apache.commons.collections4.iterators.IteratorEnumeration; import org.apache.commons.collections4.iterators.SkippingIterator; import org.apache.commons.collections4.iterators.ZippingIterator; import org.apache.commons.collections4.keyvalue.AbstractKeyValue; @@ -65,39 +70,77 @@ import org.apache.commons.collections4.keyvalue.DefaultKeyValue; import org.apache.commons.collections4.keyvalue.DefaultMapEntry; import org.apache.commons.collections4.keyvalue.TiedMapEntry; import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry; +import org.apache.commons.collections4.map.HashedMap; +import org.apache.commons.collections4.map.LinkedMap; import org.apache.commons.collections4.map.MultiValueMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; +import org.apache.commons.collections4.multiset.HashMultiSet; +import org.apache.commons.collections4.trie.PatriciaTrie; // Test case generated by GenerateFlowTestCase.ql public class Test { static Object getArrayElement(Object[] container) { return container[0]; } - static Object getElement(Iterable container) { return container.iterator().next(); } + static Object getElement(Enumeration container) { return container.nextElement(); } + static T getElement(Iterable container) { return container.iterator().next(); } + static Object getElement(Iterator container) { return container.next(); } + static Object getElement(MultiSet.Entry container) { return container.getElement(); } static Object getMapKey(AbstractKeyValue container) { return container.getKey(); } static Object getMapKeyFromEntry(Map.Entry container) { return container.getKey(); } static Object getMapKey(AbstractMapEntryDecorator container) { return container.getKey(); } static Object getMapKey(Map container) { return container.keySet().iterator().next(); } + static Object getMapKey(MultiValuedMap container) { return container.keySet().iterator().next(); } + static Object getMapKeyFromPut(Put container) { return null; } static Object getMapValue(AbstractKeyValue container) { return container.getValue(); } static Object getMapValueFromEntry(Map.Entry container) { return container.getValue(); } static Object getMapValue(AbstractMapEntryDecorator container) { return container.getValue(); } static Object getMapValue(Map container) { return container.get(null); } + static Object getMapValue(MapIterator container) { return container.getValue(); } + static Collection getMapValue(MultiValuedMap container) { return container.get(null); } + static Object getMapValueFromPut(Put container) { return null; } Object[] newWithArrayElement(Object element) { return new Object[] {element}; } - Iterable newWithElement(String element) { Vector v = new Vector(); v.add(element); return v; } + ArrayStack newArrayStackWithElement(String element) { ArrayStack a = new ArrayStack(); a.push(element); return a; } + Enumeration newEnumerationWithElement(String element) { return new IteratorEnumeration(newVectorWithElement(element).iterator()); } + FluentIterable newFluentIterableWithElement(String element) { return FluentIterable.of(element); } + ListIterator newListIteratorWithElement(String element) { return newVectorWithElement(element).listIterator(); } + MultiSet.Entry newMultiSetEntryWithElement(String element) { return getElement(newMultiSetWithElement(element).entrySet()); } + MultiSet newMultiSetWithElement(String element) { HashMultiSet h = new HashMultiSet(); h.add(element); return h; } + Queue newQueueWithElement(String element) { LinkedList q = new LinkedList(); q.add(element); return q; } + MySetView newSetViewWithElement(String element) { MySetView s = new MySetView(); s.add(element); return s; } + TreeBag newTreeBagWithElement(String element) { TreeBag b = new TreeBag(); b.add(element); return b; } + TreeSet newTreeSetWithElement(String element) { TreeSet h = new TreeSet(); h.add(element); return h; } + Vector newVectorWithElement(String element) { Vector v = new Vector(); v.add(element); return v; } + Vector> newVectorWithElement(Iterable element) { Vector> v = new Vector>(); v.add(element); return v; } + TreeBidiMap newTreeBidiMapWithMapKey(Object element) { TreeBidiMap m = new TreeBidiMap(); m.put(element,null); return m; } MyAbstractKeyValue newMAKVWithMapKey(Object element) { return new MyAbstractKeyValue(element,null); } DefaultKeyValue newDKVWithMapKey(Object element) { return new DefaultKeyValue(element,null); } + HashedMap newHashedMapWithMapKey(Object element) { HashedMap m = new HashedMap(); m.put(element,null); return m; } MyAbstractMapEntry newMAMEWithMapKey(Object element) { return new MyAbstractMapEntry(element,null); } MyAbstractMapEntryDecorator newMAMEDWithMapKey(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapKey(element)); } + // MultiMap newMMWithMapKey(Object element) { MultiMap m = new MultiValueMap(); m.put(element,null); return m; } + MultiValuedMap newMVMWithMapKey(Object element) { MultiValuedMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } + OrderedMapIterator newOMIWithElement(Object element) { LinkedMap m = new LinkedMap(); m.put(element,null); return m.mapIterator(); } ResourceBundle newRBWithMapKey(Object element) { return (ResourceBundle)null; } SortedMap newTreeMapWithMapKey(Object element) { SortedMap m = new TreeMap(); m.put(element,null); return m; } - TiedMapEntry newTMEWithMapKey(Object element) { return new TiedMapEntry(newTreeMapWithMapKey(element),element); } + Trie newTrieWithMapKey(Object element) { Trie m = new PatriciaTrie(); m.put(element,null); return m; } + TiedMapEntry newTMEWithMapKey(Object element) { return new TiedMapEntry(new TreeMap(),element); } + TreeBidiMap newTreeBidiMapWithMapValue(Object element) { TreeBidiMap m = new TreeBidiMap(); m.put(null,element); return m; } MyAbstractKeyValue newMAKVWithMapValue(Object element) { return new MyAbstractKeyValue(null,element); } DefaultKeyValue newDKVWithMapValue(Object element) { return new DefaultKeyValue(null,element); } + HashedMap newHashedMapWithMapValue(Object element) { HashedMap m = new HashedMap(); m.put(null,element); return m; } MyAbstractMapEntry newMAMEWithMapValue(Object element) { return new MyAbstractMapEntry(null,element); } MyAbstractMapEntryDecorator newMAMEDWithMapValue(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapValue(element)); } + MultiMap newMMWithMapValue(Object element) { MultiMap m = new MultiValueMap(); m.put(null,element); return m; } + ArrayListValuedHashMap newALVHMWithMapValue(Object element) { ArrayListValuedHashMap m = new ArrayListValuedHashMap(); m.put(null,element); return m; } + HashSetValuedHashMap newHSVHMWithMapValue(Object element) { HashSetValuedHashMap m = new HashSetValuedHashMap(); m.put(null,element); return m; } + OrderedMapIterator newOMIWithMapValue(Object element) { LinkedMap m = new LinkedMap(); m.put(null,element); return m.mapIterator(); } ResourceBundle newRBWithMapValue(Object element) { return (ResourceBundle)null; } SortedMap newTreeMapWithMapValue(Object element) { SortedMap m = new TreeMap(); m.put(null,element); return m; } + Trie newTrieWithMapValue(Object element) { Trie m = new PatriciaTrie(); m.put(null,element); return m; } TiedMapEntry newTMEWithMapValue(Object element) { return new TiedMapEntry(newTreeMapWithMapValue(element),null); } UnmodifiableMapEntry newUMEWithMapValue(Object element) { return new UnmodifiableMapEntry(null,element); } @@ -138,6 +181,15 @@ public class Test { } } + class MySetView extends SetUtils.SetView { + MySetView() { super(); } + + @Override + protected Iterator createIterator() { return null; } + + Iterator myCreateIterator() { return createIterator(); } + } + public void test() { { @@ -171,21 +223,21 @@ public class Test { { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - DefaultKeyValue in = newDKVWithMapValue(source()); + DefaultKeyValue in = newDKVWithMapValue((String)source()); out = in.setKey(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue(source()); + MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.mySetKey(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue(source()); + MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.mySetKey((Object)null); sink(out); // $ hasValueFlow } @@ -220,56 +272,56 @@ public class Test { { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - UnmodifiableMapEntry in = newUMEWithMapValue(source()); + UnmodifiableMapEntry in = newUMEWithMapValue((String)source()); out = in.setValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - DefaultKeyValue in = newDKVWithMapValue(source()); + DefaultKeyValue in = newDKVWithMapValue((String)source()); out = in.setValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - AbstractMapEntry in = newMAMEWithMapValue(source()); + AbstractMapEntry in = newMAMEWithMapValue((String)source()); out = in.setValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - AbstractMapEntry in = newMAMEWithMapValue(source()); + AbstractMapEntry in = newMAMEWithMapValue((String)source()); out = in.setValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue(source()); + MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.mySetValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue(source()); + MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.mySetValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" String out = null; - AbstractKeyValue in = newMAKVWithMapKey(source()); + AbstractKeyValue in = newMAKVWithMapKey((String)source()); out = in.toString(); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" String out = null; - AbstractKeyValue in = newMAKVWithMapValue(source()); + AbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.toString(); sink(out); // $ hasTaintFlow } @@ -290,70 +342,70 @@ public class Test { { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value" AbstractMapEntryDecorator out = null; - Map.Entry in = newMAMEWithMapKey(source()); + Map.Entry in = newMAMEWithMapKey((String)source()); out = new MyAbstractMapEntryDecorator(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value" AbstractMapEntryDecorator out = null; - Map.Entry in = newMAMEWithMapValue(source()); + Map.Entry in = newMAMEWithMapValue((String)source()); out = new MyAbstractMapEntryDecorator(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map.Entry out = null; - MyAbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); + MyAbstractMapEntryDecorator in = newMAMEDWithMapKey((String)source()); out = in.myGetMapEntry(); sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value" Map.Entry out = null; - MyAbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); + MyAbstractMapEntryDecorator in = newMAMEDWithMapValue((String)source()); out = in.myGetMapEntry(); sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" String out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); + AbstractMapEntryDecorator in = newMAMEDWithMapKey((String)source()); out = in.toString(); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" String out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); + AbstractMapEntryDecorator in = newMAMEDWithMapValue((String)source()); out = in.toString(); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; - Map.Entry in = newMAMEWithMapKey(source()); + Map.Entry in = newMAMEWithMapKey((String)source()); out = new DefaultKeyValue(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultKeyValue out = null; - Map.Entry in = newMAMEWithMapValue(source()); + Map.Entry in = newMAMEWithMapValue((String)source()); out = new DefaultKeyValue(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; - KeyValue in = newMAKVWithMapKey(source()); + KeyValue in = newMAKVWithMapKey((String)source()); out = new DefaultKeyValue(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultKeyValue out = null; - KeyValue in = newMAKVWithMapValue(source()); + KeyValue in = newMAKVWithMapValue((String)source()); out = new DefaultKeyValue(in); sink(getMapValue(out)); // $ hasValueFlow } @@ -374,42 +426,42 @@ public class Test { { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map.Entry out = null; - DefaultKeyValue in = newDKVWithMapKey(source()); + DefaultKeyValue in = newDKVWithMapKey((String)source()); out = in.toMapEntry(); sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value" Map.Entry out = null; - DefaultKeyValue in = newDKVWithMapValue(source()); + DefaultKeyValue in = newDKVWithMapValue((String)source()); out = in.toMapEntry(); sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultMapEntry out = null; - Map.Entry in = newMAMEWithMapKey(source()); + Map.Entry in = newMAMEWithMapKey((String)source()); out = new DefaultMapEntry(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultMapEntry out = null; - Map.Entry in = newMAMEWithMapValue(source()); + Map.Entry in = newMAMEWithMapValue((String)source()); out = new DefaultMapEntry(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultMapEntry out = null; - KeyValue in = newMAKVWithMapKey(source()); + KeyValue in = newMAKVWithMapKey((String)source()); out = new DefaultMapEntry(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" DefaultMapEntry out = null; - KeyValue in = newMAKVWithMapValue(source()); + KeyValue in = newMAKVWithMapValue((String)source()); out = new DefaultMapEntry(in); sink(getMapValue(out)); // $ hasValueFlow } @@ -437,35 +489,35 @@ public class Test { { // "org.apache.commons.collections4.keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value" TiedMapEntry out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = new TiedMapEntry(in, null); sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" UnmodifiableMapEntry out = null; - Map.Entry in = newMAMEWithMapKey(source()); + Map.Entry in = newMAMEWithMapKey((String)source()); out = new UnmodifiableMapEntry(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; - Map.Entry in = newMAMEWithMapValue(source()); + Map.Entry in = newMAMEWithMapValue((String)source()); out = new UnmodifiableMapEntry(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value" UnmodifiableMapEntry out = null; - KeyValue in = newMAKVWithMapKey(source()); + KeyValue in = newMAKVWithMapKey((String)source()); out = new UnmodifiableMapEntry(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; - KeyValue in = newMAKVWithMapValue(source()); + KeyValue in = newMAKVWithMapValue((String)source()); out = new UnmodifiableMapEntry(in); sink(getMapValue(out)); // $ hasValueFlow } @@ -486,56 +538,56 @@ public class Test { { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - TiedMapEntry in = newTMEWithMapKey(source()); + TiedMapEntry in = newTMEWithMapKey((String)source()); out = in.getKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - KeyValue in = newMAKVWithMapKey(source()); + KeyValue in = newMAKVWithMapKey((String)source()); out = in.getKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapKey(source()); + AbstractMapEntryDecorator in = newMAMEDWithMapKey((String)source()); out = in.getKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - AbstractKeyValue in = newMAKVWithMapKey(source()); + AbstractKeyValue in = newMAKVWithMapKey((String)source()); out = in.getKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - TiedMapEntry in = newTMEWithMapValue(source()); + TiedMapEntry in = newTMEWithMapValue((String)source()); out = in.getValue(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - KeyValue in = newMAKVWithMapValue(source()); + KeyValue in = newMAKVWithMapValue((String)source()); out = in.getValue(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapValue(source()); + AbstractMapEntryDecorator in = newMAMEDWithMapValue((String)source()); out = in.getValue(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - AbstractKeyValue in = newMAKVWithMapValue(source()); + AbstractKeyValue in = newMAKVWithMapValue((String)source()); out = in.getValue(); sink(out); // $ hasValueFlow } @@ -549,28 +601,28 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.fixedSizeMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.fixedSizeMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.fixedSizeSortedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.fixedSizeSortedMap(in); sink(getMapValue(out)); // $ hasValueFlow } @@ -584,14 +636,14 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getMap(in, null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getMap(in, null); sink(out); // $ hasValueFlow } @@ -605,14 +657,14 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value" Object out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getObject(in, null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value" Object out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getObject(in, null); sink(out); // $ hasValueFlow } @@ -626,175 +678,175 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value" String out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getString(in, null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value" String out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.getString(in, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapKey of Argument[0];MapValue of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.invertMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapValue of Argument[0];MapKey of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.invertMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.iterableMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.iterableMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableSortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.iterableSortedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableSortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.iterableSortedMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.lazyMap(in, (Transformer)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.lazyMap(in, (Factory)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.lazyMap(in, (Transformer)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.lazyMap(in, (Factory)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.lazySortedMap(in, (Transformer)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.lazySortedMap(in, (Factory)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.lazySortedMap(in, (Transformer)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.lazySortedMap(in, (Factory)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.multiValueMap(in, (Factory)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.multiValueMap(in, (Class)null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.multiValueMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.multiValueMap(in, (Factory)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.multiValueMap(in, (Class)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValueMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.multiValueMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" OrderedMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.orderedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" OrderedMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.orderedMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value" Map out = null; - Iterable in = newWithElement((String)source()); + Iterable in = newVectorWithElement((String)source()); MapUtils.populateMap(out, in, (Transformer)null); sink(getMapValue(out)); // $ hasValueFlow } @@ -803,119 +855,119 @@ public class Test { // which overload it should choose unless you put the generic types in correctly // "org.apache.commons.collections4;MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value" MultiMap out = null; - Iterable in = newWithElement((String)source()); + Iterable in = newVectorWithElement((String)source()); MapUtils.populateMap(out, in, (Transformer)null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.predicatedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.predicatedMap(in, null, null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.predicatedSortedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.predicatedSortedMap(in, null, null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(source()); + Object[] in = newWithArrayElement((String)source()); MapUtils.putAll(out, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(source()); + Object[] in = newWithArrayElement((String)source()); out = MapUtils.putAll(null, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(source()); + Object[] in = newWithArrayElement((String)source()); MapUtils.putAll(out, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(source()); + Object[] in = newWithArrayElement((String)source()); out = MapUtils.putAll(null, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(newWithArrayElement(source())); + Object[] in = newWithArrayElement(newWithArrayElement((String)source())); MapUtils.putAll(out, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(newWithArrayElement(source())); + Object[] in = newWithArrayElement(newWithArrayElement((String)source())); out = MapUtils.putAll(null, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(newWithArrayElement(source())); + Object[] in = newWithArrayElement(newWithArrayElement((String)source())); MapUtils.putAll(out, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(newWithArrayElement(source())); + Object[] in = newWithArrayElement(newWithArrayElement((String)source())); out = MapUtils.putAll(null, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(newMAKVWithMapKey(source())); + Object[] in = newWithArrayElement(newMAKVWithMapKey((String)source())); MapUtils.putAll(out, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(newMAKVWithMapKey(source())); + Object[] in = newWithArrayElement(newMAKVWithMapKey((String)source())); out = MapUtils.putAll(null, in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of Argument[0];value" Map out = null; - Object[] in = newWithArrayElement(newMAKVWithMapValue(source())); + Object[] in = newWithArrayElement(newMAKVWithMapValue((String)source())); MapUtils.putAll(out, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of ReturnValue;value" Map out = null; - Object[] in = newWithArrayElement(newMAKVWithMapValue(source())); + Object[] in = newWithArrayElement(newMAKVWithMapValue((String)source())); out = MapUtils.putAll(null, in); sink(getMapValue(out)); // $ hasValueFlow } @@ -936,119 +988,119 @@ public class Test { { // "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.synchronizedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.synchronizedMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.synchronizedSortedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.synchronizedSortedMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;toMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; - ResourceBundle in = newRBWithMapKey(source()); + ResourceBundle in = newRBWithMapKey((String)source()); out = MapUtils.toMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;toMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; - ResourceBundle in = newRBWithMapValue(source()); + ResourceBundle in = newRBWithMapValue((String)source()); out = MapUtils.toMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.transformedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.transformedMap(in, null, null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.transformedSortedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.transformedSortedMap(in, null, null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out = MapUtils.unmodifiableMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; - Map in = newTreeMapWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out = MapUtils.unmodifiableMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapKey(source()); + SortedMap in = newTreeMapWithMapKey((String)source()); out = MapUtils.unmodifiableSortedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" SortedMap out = null; - SortedMap in = newTreeMapWithMapValue(source()); + SortedMap in = newTreeMapWithMapValue((String)source()); out = MapUtils.unmodifiableSortedMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value" Object out = null; - ArrayStack in = (ArrayStack)newWithElement(source()); + ArrayStack in = newArrayStackWithElement((String)source()); out = in.peek(0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value" Object out = null; - ArrayStack in = (ArrayStack)newWithElement(source()); + ArrayStack in = newArrayStackWithElement((String)source()); out = in.peek(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value" Object out = null; - ArrayStack in = (ArrayStack)newWithElement(source()); + ArrayStack in = newArrayStackWithElement((String)source()); out = in.pop(); sink(out); // $ hasValueFlow } @@ -1076,126 +1128,126 @@ public class Test { { // "org.apache.commons.collections4;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value" Set out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = newTreeBagWithElement((String)source()); out = in.uniqueSet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = newTreeBagWithElement((String)source()); out = BagUtils.collectionBag(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = (Bag)newTreeBagWithElement((String)source()); out = BagUtils.predicatedBag(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value" SortedBag out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = BagUtils.predicatedSortedBag(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = newTreeBagWithElement((String)source()); out = BagUtils.synchronizedBag(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value" SortedBag out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = BagUtils.synchronizedSortedBag(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = newTreeBagWithElement((String)source()); out = BagUtils.transformingBag(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value" SortedBag out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = BagUtils.transformingSortedBag(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newWithElement(source()); + Bag in = newTreeBagWithElement((String)source()); out = BagUtils.unmodifiableBag(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" SortedBag out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = BagUtils.unmodifiableSortedBag(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - BidiMap in = (BidiMap)newWithMapKey(source()); + BidiMap in = newTreeBidiMapWithMapKey((String)source()); out = in.getKey(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value" BidiMap out = null; - BidiMap in = (BidiMap)newWithMapKey(source()); + BidiMap in = newTreeBidiMapWithMapKey((String)source()); out = in.inverseBidiMap(); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value" BidiMap out = null; - BidiMap in = (BidiMap)newWithMapValue(source()); + BidiMap in = newTreeBidiMapWithMapValue((String)source()); out = in.inverseBidiMap(); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - BidiMap in = (BidiMap)newWithMapKey(source()); + BidiMap in = newTreeBidiMapWithMapKey((String)source()); out = in.removeValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value" Collection out = null; - Enumeration in = (Enumeration)newWithElement(source()); + Enumeration in = newEnumerationWithElement((String)source()); CollectionUtils.addAll(out, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); CollectionUtils.addAll(out, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value" Collection out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); CollectionUtils.addAll(out, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value" Collection out = null; - C[] in = (C[])newWithArrayElement(source()); + String[] in = (String[])newWithArrayElement((String)source()); CollectionUtils.addAll(out, in); sink(getElement(out)); // $ hasValueFlow } @@ -1209,70 +1261,70 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(in, null, null, false); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(in, (Iterable)null, false); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(in, (Iterable)null, (Comparator)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(null, in, null, false); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate((Iterable)null, in, false); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.collate((Iterable)null, in, (Comparator)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.disjunction(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.disjunction(null, in); sink(getElement(out)); // $ hasValueFlow } @@ -1286,252 +1338,252 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value" Object out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.extractSingleton(in); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.find(in, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value" Object out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value" Map.Entry out = null; - Map in = (Map)newWithMapKey(source()); + Map in = (Map)newTreeMapWithMapKey((String)source()); out = CollectionUtils.get(in, 0); - sink(getMapKey(out)); // $ hasValueFlow + sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value" Map.Entry out = null; - Map in = (Map)newWithMapValue(source()); + Map in = (Map)newTreeMapWithMapValue((String)source()); out = CollectionUtils.get(in, 0); - sink(getMapValue(out)); // $ hasValueFlow + sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value" Object out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value" Object out = null; - Object in = (Object)newWithElement(source()); + Object in = (Object)newVectorWithElement((String)source()); out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value" - Object out = null; - Object in = (Object)newWithMapKey(source()); - out = CollectionUtils.get(in, 0); - sink(getMapKey(out)); // $ hasValueFlow + Map.Entry out = null; + Object in = (Object)newTreeMapWithMapKey((String)source()); + out = (Map.Entry)CollectionUtils.get(in, 0); + sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value" - Object out = null; - Object in = (Object)newWithMapValue(source()); - out = CollectionUtils.get(in, 0); - sink(getMapValue(out)); // $ hasValueFlow + Map.Entry out = null; + Object in = (Object)newTreeMapWithMapValue((String)source()); + out = (Map.Entry)CollectionUtils.get(in, 0); + sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value" Map out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.getCardinalityMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.intersection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.intersection(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.permutations(in); - sink(getElement(getElement(out))); // $ hasValueFlow + sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.predicatedCollection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.removeAll(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.removeAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.retainAll(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.retainAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); CollectionUtils.select(in, null, out, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); CollectionUtils.select(in, null, out); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); CollectionUtils.select(in, null, null, out); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.select(in, null, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.select(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.select(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); CollectionUtils.selectRejected(in, null, out); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.selectRejected(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.selectRejected(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.subtract(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.subtract(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.synchronizedCollection(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.transformingCollection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.union(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" Collection out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.union(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = CollectionUtils.unmodifiableCollection(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value" Object out = null; - Enumeration in = (Enumeration)newWithElement(source()); + Enumeration in = newEnumerationWithElement((String)source()); out = EnumerationUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value" List out = null; - Enumeration in = (Enumeration)newWithElement(source()); + Enumeration in = newEnumerationWithElement((String)source()); out = EnumerationUtils.toList(in); sink(getElement(out)); // $ hasValueFlow } @@ -1545,14 +1597,14 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.append((Iterable)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); FluentIterable instance = null; out = instance.append(in); sink(getElement(out)); // $ hasValueFlow @@ -1560,35 +1612,35 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.append(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value" Enumeration out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.asEnumeration(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.collate(null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.collate(null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); FluentIterable instance = null; out = instance.collate(in, null); sink(getElement(out)); // $ hasValueFlow @@ -1596,7 +1648,7 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); FluentIterable instance = null; out = instance.collate(in); sink(getElement(out)); // $ hasValueFlow @@ -1604,49 +1656,49 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value" Collection out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); in.copyInto(out); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.eval(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.filter(null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value" Object out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.get(0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.limit(0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.loop(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); out = FluentIterable.of(in); sink(getElement(out)); // $ hasValueFlow } @@ -1660,246 +1712,246 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - T[] in = (T[])newWithArrayElement(source()); + String[] in = (String[])newWithArrayElement((String)source()); out = FluentIterable.of(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.reverse(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.skip(0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value" List out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.toList(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint" String out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.toString(); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.unique(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.unmodifiable(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; - FluentIterable in = (FluentIterable)newWithElement(source()); + FluentIterable in = newFluentIterableWithElement((String)source()); out = in.zip((Iterable)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); FluentIterable instance = null; out = instance.zip(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" - Set out = null; - Get in = (Get)newWithMapKey(source()); + Set out = null; + Get in = newTrieWithMapKey((String)source()); out = in.entrySet(); - sink(getMapKey(getElement(out))); // $ hasValueFlow + sink(getMapKeyFromEntry(getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value" - Set out = null; - Get in = (Get)newWithMapValue(source()); + Set out = null; + Get in = newTrieWithMapValue((String)source()); out = in.entrySet(); - sink(getMapValue(getElement(out))); // $ hasValueFlow + sink(getMapValueFromEntry(getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MultiMap in = (MultiMap)newWithMapValue(source()); + MultiMap in = newMMWithMapValue((String)source()); out = in.get(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - Get in = (Get)newWithMapValue(source()); + Get in = newTrieWithMapValue((String)source()); out = in.get(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; - Get in = (Get)newWithMapKey(source()); + Get in = newTrieWithMapKey((String)source()); out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MultiMap in = (MultiMap)newWithMapValue(source()); + MultiMap in = newMMWithMapValue((String)source()); out = in.remove(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" Object out = null; - Get in = (Get)newWithMapValue(source()); + Get in = newTrieWithMapValue((String)source()); out = in.remove(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" Set out = null; - BidiMap in = (BidiMap)newWithMapValue(source()); + BidiMap in = newTreeBidiMapWithMapValue((String)source()); out = in.values(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; - MultiMap in = (MultiMap)newWithMapValue(source()); + MultiMap in = newMMWithMapValue((String)source()); out = in.values(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; - Get in = (Get)newWithMapValue(source()); + Get in = newTrieWithMapValue((String)source()); out = in.values(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" MapIterator out = null; - IterableGet in = (IterableGet)newWithMapKey(source()); + IterableGet in = newHashedMapWithMapKey((String)source()); out = in.mapIterator(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value" MapIterator out = null; - IterableGet in = (IterableGet)newWithMapValue(source()); + IterableGet in = newHashedMapWithMapValue((String)source()); out = in.mapIterator(); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.boundedIterable(in, 0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(in, null, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.chainedIterable(null, null, null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.collatedIterable(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.collatedIterable(null, null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.collatedIterable(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.collatedIterable(null, in); sink(getElement(out)); // $ hasValueFlow } @@ -1913,301 +1965,301 @@ public class Test { { // "org.apache.commons.collections4;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.filteredIterable(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.find(in, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.first(in); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.loopingIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); - out = IterableUtils.partition(in, null, null); - sink(getElement(getElement(out))); // $ hasValueFlow + Iterable in = newVectorWithElement((String)source()); + out = IterableUtils.partition(in, null, (Predicate[])null); + sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); - out = IterableUtils.partition(in, (Predicate[])null); - sink(getElement(getElement(out))); // $ hasValueFlow + Iterable in = newVectorWithElement((String)source()); + out = IterableUtils.partition(in, (Predicate[])null); + sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.partition(in, (Predicate)null); - sink(getElement(getElement(out))); // $ hasValueFlow + sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.reversedIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.skippingIterable(in, 0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.toList(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.toString(in, null, null, null, null); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.toString(in, null); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.toString(in); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.uniqueIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.unmodifiableIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.zippingIterable((Iterable)null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.zippingIterable(in, (Iterable)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newVectorWithElement((String)source()); out = IterableUtils.zippingIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in, 0, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in, 0, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value" Enumeration out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.asEnumeration(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.asIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Enumeration in = (Enumeration)newWithElement(source()); + Enumeration in = newEnumerationWithElement((String)source()); out = IteratorUtils.asIterator(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Enumeration in = (Enumeration)newWithElement(source()); + Enumeration in = newEnumerationWithElement((String)source()); out = IteratorUtils.asIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.asMultipleUseIterable(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value" BoundedIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.boundedIterator(in, 0L, 0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value" BoundedIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.boundedIterator(in, 0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Collection in = (Collection)newWithElement(newWithElement(source())); + Collection in = (Collection)newVectorWithElement(newVectorWithElement((String)source())); out = IteratorUtils.chainedIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.chainedIterator(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.chainedIterator(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value" Iterator out = null; - Collection in = (Collection)newWithElement(newWithElement(source())); + Collection in = (Collection)newVectorWithElement(newVectorWithElement((String)source())); out = IteratorUtils.collatedIterator((Comparator)null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.collatedIterator(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.collatedIterator(null, null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.filteredIterator(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value" ListIterator out = null; - ListIterator in = (ListIterator)newWithElement(source()); + ListIterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.filteredListIterator(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.find(in, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.first(in); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value" Object out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.get(in, 0); sink(out); // $ hasValueFlow } @@ -2221,49 +2273,49 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)newWithArrayElement(source()); + Object in = (Object)newWithArrayElement((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)newWithElement(source()); + Object in = (Object)newVectorWithElement((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)newWithMapValue(source()); + Map in = (Map)newTreeMapWithMapValue((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = IteratorUtils.loopingIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = IteratorUtils.loopingListIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.peekingIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.pushbackIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2284,14 +2336,14 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value" SkippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.skippingIterator(in, 0L); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value" Object[] out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toArray(in); sink(getArrayElement(out)); // $ hasValueFlow } @@ -2319,84 +2371,84 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toString(in, null, null, null, null); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toString(in, null); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" String out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toString(in); sink(out); // $ hasTaintFlow } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.unmodifiableIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value" ListIterator out = null; - ListIterator in = (ListIterator)newWithElement(source()); + ListIterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.unmodifiableListIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value" MapIterator out = null; - MapIterator in = (MapIterator)newWithElement(source()); + MapIterator in = newOMIWithElement((String)source()); out = IteratorUtils.unmodifiableMapIterator(in); - sink(getElement(out)); // $ hasValueFlow + sink(getElement((Iterator)out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value" MapIterator out = null; - MapIterator in = (MapIterator)newWithMapValue(source()); + MapIterator in = newOMIWithMapValue((String)source()); out = IteratorUtils.unmodifiableMapIterator(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" ZippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.zippingIterator(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" ZippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.zippingIterator(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" ZippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.zippingIterator(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" ZippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.zippingIterator(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" ZippingIterator out = null; - Iterator in = (Iterator)newWithElement(source()); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.zippingIterator(null, null, in); sink(getElement(out)); // $ hasValueFlow } @@ -2417,28 +2469,28 @@ public class Test { { // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.intersection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.intersection(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.lazyList(in, (Transformer)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.lazyList(in, (Factory)null); sink(getElement(out)); // $ hasValueFlow } @@ -2459,147 +2511,147 @@ public class Test { { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(in, (List)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence((List)null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.partition(in, 0); - sink(getElement(getElement(out))); // $ hasValueFlow + sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.predicatedList(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = ListUtils.removeAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = ListUtils.retainAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = ListUtils.select(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newWithElement(source()); + Collection in = (Collection)newVectorWithElement((String)source()); out = ListUtils.selectRejected(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.subtract(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.sum(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.sum(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.synchronizedList(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.transformedList(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.union(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.union(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newWithElement(source()); + List in = (List)newVectorWithElement((String)source()); out = ListUtils.unmodifiableList(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value" Object out = null; - MapIterator in = (MapIterator)newWithElement(source()); + MapIterator in = newOMIWithElement((String)source()); out = in.getKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MapIterator in = (MapIterator)newWithMapValue(source()); + MapIterator in = newOMIWithMapValue((String)source()); out = in.getValue(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value" Object out = null; - MapIterator in = (MapIterator)newWithElement(source()); + MapIterator in = newOMIWithElement((String)source()); out = in.next(); sink(out); // $ hasValueFlow } @@ -2613,15 +2665,15 @@ public class Test { { // "org.apache.commons.collections4;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MapIterator in = (MapIterator)newWithMapValue(source()); + MapIterator in = newOMIWithMapValue((String)source()); out = in.setValue(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" - Object out = null; - MultiMap in = (MultiMap)newWithMapValue(newWithElement(source())); - out = in.get(null); + Collection out = null; + MultiMap in = newMMWithMapValue((String)source()); + out = (Collection)in.get(null); sink(getElement(out)); // $ hasValueFlow } { @@ -2636,12 +2688,12 @@ public class Test { MultiMap out = null; Object in = (Object)source(); out.put(null, in); - sink(getElement(getMapValue(out))); // $ hasValueFlow + sink(getElement((Collection)getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; - MultiMap in = (MultiMap)newWithMapValue(newWithElement(source())); + MultiMap in = newMMWithMapValue((String)source()); out = in.values(); sink(getElement(out)); // $ hasValueFlow } @@ -2655,63 +2707,63 @@ public class Test { { // "org.apache.commons.collections4;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value" Collection out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getCollection(in, null); - sink(out); // $ hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value" Bag out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsBag(in, null); - sink(out); // $ hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value" List out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsList(in, null); - sink(out); // $ hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value" Set out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsSet(in, null); - sink(out); // $ hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = MultiMapUtils.transformedMultiValuedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.transformedMultiValuedMap(in, null, null); - sink(getMapValue(out)); // $ hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = MultiMapUtils.unmodifiableMultiValuedMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(source()); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.unmodifiableMultiValuedMap(in); - sink(getMapValue(out)); // $ hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value" Object out = null; - MultiSet.Entry in = (MultiSet.Entry)newWithElement(source()); + MultiSet.Entry in = newMultiSetEntryWithElement((String)source()); out = in.getElement(); sink(out); // $ hasValueFlow } @@ -2731,99 +2783,99 @@ public class Test { } { // "org.apache.commons.collections4;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value" - Set out = null; - MultiSet in = (MultiSet)newWithElement(source()); + Set out = null; + MultiSet in = newMultiSetWithElement((String)source()); out = in.entrySet(); sink(getElement(getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value" Set out = null; - MultiSet in = (MultiSet)newWithElement(source()); + MultiSet in = newMultiSetWithElement((String)source()); out = in.uniqueSet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value" MultiSet out = null; - MultiSet in = (MultiSet)newWithElement(source()); + MultiSet in = newMultiSetWithElement((String)source()); out = MultiSetUtils.predicatedMultiSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value" MultiSet out = null; - MultiSet in = (MultiSet)newWithElement(source()); + MultiSet in = newMultiSetWithElement((String)source()); out = MultiSetUtils.synchronizedMultiSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" MultiSet out = null; - MultiSet in = (MultiSet)newWithElement(source()); + MultiSet in = newMultiSetWithElement((String)source()); out = MultiSetUtils.unmodifiableMultiSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value" Map out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = in.asMap(); - sink(getElement(getMapValue(out))); // $ hasValueFlow + sink(getElement((Collection)getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = in.asMap(); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Set out = null; - SetValuedMap in = (SetValuedMap)newWithMapValue(newWithElement(source())); + SetValuedMap in = newHSVHMWithMapValue((String)source()); out = in.get(null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" List out = null; - ListValuedMap in = (ListValuedMap)newWithMapValue(newWithElement(source())); + ListValuedMap in = newALVHMWithMapValue((String)source()); out = in.get(null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = in.get(null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value" MultiSet out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = in.keys(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value" MapIterator out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = in.mapIterator(); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" MapIterator out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out = in.mapIterator(); sink(getElement(out)); // $ hasValueFlow } @@ -2844,28 +2896,28 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - Map in = (Map)newWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out.putAll(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value" MultiValuedMap out = null; - Map in = (Map)newWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out.putAll(in); sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out.putAll(in); sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapKey(source()); + MultiValuedMap in = newMVMWithMapKey((String)source()); out.putAll(in); sink(getMapKey(out)); // $ hasValueFlow } @@ -2879,56 +2931,56 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value" MultiValuedMap out = null; - Iterable in = (Iterable)newWithElement(source()); + Iterable in = newFluentIterableWithElement((String)source()); out.putAll(null, in); sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; - MultiValuedMap in = (MultiValuedMap)newWithMapValue(newWithElement(source())); + MultiValuedMap in = newALVHMWithMapValue((String)source()); out = in.values(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value" Object out = null; - OrderedMapIterator in = (OrderedMapIterator)newWithElement(source()); + OrderedMapIterator in = newOMIWithElement((String)source()); out = in.previous(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value" Object out = null; - OrderedIterator in = (OrderedIterator)newWithElement(source()); + OrderedIterator in = newOMIWithElement((String)source()); out = in.previous(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - OrderedMap in = (OrderedMap)newWithMapKey(source()); + OrderedMap in = newTreeBidiMapWithMapKey((String)source()); out = in.firstKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - OrderedMap in = (OrderedMap)newWithMapKey(source()); + OrderedMap in = newTreeBidiMapWithMapKey((String)source()); out = in.lastKey(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - OrderedMap in = (OrderedMap)newWithMapKey(source()); + OrderedMap in = newTreeBidiMapWithMapKey((String)source()); out = in.nextKey(null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - OrderedMap in = (OrderedMap)newWithMapKey(source()); + OrderedMap in = newTreeBidiMapWithMapKey((String)source()); out = in.previousKey(null); sink(out); // $ hasValueFlow } @@ -2937,7 +2989,7 @@ public class Test { Put out = null; Object in = (Object)source(); out.put(in, null); - sink(getMapKey(out)); // $ hasValueFlow + sink(getMapKeyFromPut(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" @@ -2958,7 +3010,7 @@ public class Test { Put out = null; Object in = (Object)source(); out.put(null, in); - sink(getMapValue(out)); // $ hasValueFlow + sink(getMapValueFromPut(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" @@ -2977,91 +3029,91 @@ public class Test { { // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - Put in = (Put)newWithMapValue(source()); + Put in = newHashedMapWithMapValue((String)source()); out = in.put(null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - MultiMap in = (MultiMap)newWithMapValue(source()); + MultiMap in = newMMWithMapValue((String)source()); out = in.put(null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; - BidiMap in = (BidiMap)newWithMapValue(source()); + BidiMap in = newTreeBidiMapWithMapValue((String)source()); out = in.put(null, null); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" Put out = null; - Map in = (Map)newWithMapKey(source()); + Map in = newTreeMapWithMapKey((String)source()); out.putAll(in); - sink(getMapKey(out)); // $ hasValueFlow + sink(getMapKeyFromPut(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" Put out = null; - Map in = (Map)newWithMapValue(source()); + Map in = newTreeMapWithMapValue((String)source()); out.putAll(in); - sink(getMapValue(out)); // $ hasValueFlow + sink(getMapValueFromPut(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value" Queue out = null; - Queue in = (Queue)newWithElement(source()); + Queue in = newQueueWithElement((String)source()); out = QueueUtils.predicatedQueue(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value" Queue out = null; - Queue in = (Queue)newWithElement(source()); + Queue in = newQueueWithElement((String)source()); out = QueueUtils.synchronizedQueue(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value" Queue out = null; - Queue in = (Queue)newWithElement(source()); + Queue in = newQueueWithElement((String)source()); out = QueueUtils.transformingQueue(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" Queue out = null; - Queue in = (Queue)newWithElement(source()); + Queue in = newQueueWithElement((String)source()); out = QueueUtils.unmodifiableQueue(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value" Set out = null; - SetUtils.SetView in = (SetUtils.SetView)newWithElement(source()); + SetUtils.SetView in = newSetViewWithElement((String)source()); in.copyInto(out); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value" Iterator out = null; - SetUtils.SetView in = (SetUtils.SetView)newWithElement(source()); - out = in.createIterator(); + MySetView in = newSetViewWithElement((String)source()); + out = in.myCreateIterator(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.difference(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.difference(null, in); sink(getElement(out)); // $ hasValueFlow } @@ -3075,182 +3127,182 @@ public class Test { { // "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.intersection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.intersection(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value" Set out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.orderedSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - NavigableSet in = (NavigableSet)newWithElement(source()); + NavigableSet in = newTreeSetWithElement((String)source()); out = SetUtils.predicatedNavigableSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value" Set out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.predicatedSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - SortedSet in = (SortedSet)newWithElement(source()); + SortedSet in = newTreeSetWithElement((String)source()); out = SetUtils.predicatedSortedSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value" Set out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.synchronizedSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - SortedSet in = (SortedSet)newWithElement(source()); + SortedSet in = newTreeSetWithElement((String)source()); out = SetUtils.synchronizedSortedSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - NavigableSet in = (NavigableSet)newWithElement(source()); + NavigableSet in = newTreeSetWithElement((String)source()); out = SetUtils.transformedNavigableSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value" Set out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.transformedSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - SortedSet in = (SortedSet)newWithElement(source()); + SortedSet in = newTreeSetWithElement((String)source()); out = SetUtils.transformedSortedSet(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.union(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" SetUtils.SetView out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.union(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - NavigableSet in = (NavigableSet)newWithElement(source()); + NavigableSet in = newTreeSetWithElement((String)source()); out = SetUtils.unmodifiableNavigableSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value" Set out = null; - Set in = (Set)newWithElement(source()); + Set in = newTreeSetWithElement((String)source()); out = SetUtils.unmodifiableSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" SortedSet out = null; - SortedSet in = (SortedSet)newWithElement(source()); + SortedSet in = newTreeSetWithElement((String)source()); out = SetUtils.unmodifiableSortedSet(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value" Object out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = in.first(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value" Object out = null; - SortedBag in = (SortedBag)newWithElement(source()); + SortedBag in = newTreeBagWithElement((String)source()); out = in.last(); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" IterableMap out = null; - Get in = (Get)newWithMapKey(source()); + Get in = newHashedMapWithMapKey((String)source()); out = SplitMapUtils.readableMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" IterableMap out = null; - Get in = (Get)newWithMapValue(source()); + Get in = newHashedMapWithMapValue((String)source()); out = SplitMapUtils.readableMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" Map out = null; - Put in = (Put)newWithMapKey(source()); + Put in = newHashedMapWithMapKey((String)source()); out = SplitMapUtils.writableMap(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" Map out = null; - Put in = (Put)newWithMapValue(source()); + Put in = newHashedMapWithMapValue((String)source()); out = SplitMapUtils.writableMap(in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" SortedMap out = null; - Trie in = (Trie)newWithMapKey(source()); + Trie in = newTrieWithMapKey((String)source()); out = in.prefixMap(null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value" SortedMap out = null; - Trie in = (Trie)newWithMapValue(source()); + Trie in = newTrieWithMapValue((String)source()); out = in.prefixMap(null); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value" Trie out = null; - Trie in = (Trie)newWithMapKey(source()); + Trie in = newTrieWithMapKey((String)source()); out = TrieUtils.unmodifiableTrie(in); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" Trie out = null; - Trie in = (Trie)newWithMapValue(source()); + Trie in = newTrieWithMapValue((String)source()); out = TrieUtils.unmodifiableTrie(in); sink(getMapValue(out)); // $ hasValueFlow } diff --git a/java/ql/test/library-tests/frameworks/apache-collections/test.ql b/java/ql/test/library-tests/frameworks/apache-collections/test.ql index 611fcd302ee..76541c1843d 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/test.ql +++ b/java/ql/test/library-tests/frameworks/apache-collections/test.ql @@ -9,6 +9,9 @@ class SummaryModelTest extends SummaryModelCsv { row = [ //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + "org.apache.commons.collections4.iterators;IteratorEnumeration;true;IteratorEnumeration;;;Element of Argument[0];Element of Argument[-1];value", + "generatedtest;Test;false;getMapKeyFromPut;;;MapKey of Argument[0];ReturnValue;value", + "generatedtest;Test;false;getMapValueFromPut;;;MapValue of Argument[0];ReturnValue;value", "generatedtest;Test;false;newRBWithMapValue;;;Argument[0];MapValue of ReturnValue;value", "generatedtest;Test;false;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value" ] From db2f9add53157eb4f1fd68ceb82ce5d1fd1da52e Mon Sep 17 00:00:00 2001 From: edvraa <80588099+edvraa@users.noreply.github.com> Date: Wed, 4 Aug 2021 18:37:17 +0300 Subject: [PATCH 146/429] Post merge --- .../dataflow/UnsafeDeserialization.qll | 913 ------------------ .../dataflow/UnsafeDeserializationQuery.qll | 910 ++++++++++++++++- 2 files changed, 867 insertions(+), 956 deletions(-) delete mode 100644 csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll deleted file mode 100644 index 69aaab1fed2..00000000000 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ /dev/null @@ -1,913 +0,0 @@ -/** - * Provides a taint-tracking configuration for reasoning about uncontrolled data - * in calls to unsafe deserializers (XML, JSON, XAML). - */ - -import csharp - -module UnsafeDeserialization { - private import semmle.code.csharp.serialization.Deserializers - private import semmle.code.csharp.dataflow.TaintTracking2 - private import semmle.code.csharp.security.dataflow.flowsources.Remote - private import semmle.code.csharp.security.dataflow.flowsources.Local - - /** - * A data flow source for unsafe deserialization vulnerabilities. - */ - abstract class Source extends DataFlow::Node { } - - /** - * A data flow sink for unsafe deserialization vulnerabilities. - */ - abstract class Sink extends DataFlow::Node { } - - /** - * A data flow sink for unsafe deserialization vulnerabilities to an instance method. - */ - abstract private class InstanceMethodSink extends Sink { - InstanceMethodSink() { - not exists( - SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage, - MethodCall mc - | - safeConstructorTracking.hasFlow(_, safeTypeUsage) and - mc.getQualifier() = safeTypeUsage.asExpr() and - mc.getAnArgument() = this.asExpr() - ) - } - } - - /** - * A data flow sink for unsafe deserialization vulnerabilities to a static method or constructor call. - */ - abstract private class ConstructorOrStaticMethodSink extends Sink { } - - /** - * A sanitizer for unsafe deserialization vulnerabilities. - */ - abstract class Sanitizer extends DataFlow::Node { } - - private class RemoteSource extends Source { - RemoteSource() { this instanceof RemoteFlowSource } - } - - private class LocalSource extends Source { - LocalSource() { this instanceof LocalFlowSource } - } - - /** - * User input to object method call deserialization flow tracking. - */ - class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration { - TaintToObjectMethodTrackingConfig() { this = "TaintToObjectMethodTrackingConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof InstanceMethodSink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } - - /** - * User input to `JsonConvert` call deserialization flow tracking. - */ - class JsonConvertTrackingConfig extends TaintTracking::Configuration { - JsonConvertTrackingConfig() { this = "JsonConvertTrackingConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { - sink instanceof NewtonsoftJsonConvertDeserializeObjectMethodSink - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } - - /** - * Tracks unsafe `TypeNameHandling` setting to `JsonConvert` call - */ - class TypeNameTrackingConfig extends DataFlow::Configuration { - TypeNameTrackingConfig() { this = "TypeNameTrackingConfig" } - - override predicate isSource(DataFlow::Node source) { - ( - source.asExpr() instanceof MemberConstantAccess and - source.getType() instanceof TypeNameHandlingEnum - or - source.asExpr() instanceof IntegerLiteral - ) and - source.asExpr().hasValue() and - not source.asExpr().getValue() = "0" - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m, Expr expr | - m = mc.getTarget() and - ( - not mc.getArgument(0).hasValue() and - m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod - ) and - expr = mc.getAnArgument() and - sink.asExpr() = expr and - expr.getType() instanceof JsonSerializerSettingsClass - ) - } - - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - node1.asExpr() instanceof IntegerLiteral and - node2.asExpr().(CastExpr).getExpr() = node1.asExpr() - or - node1.getType() instanceof TypeNameHandlingEnum and - exists(PropertyWrite pw, Property p, Assignment a | - a.getLValue() = pw and - pw.getProperty() = p and - p.getDeclaringType() instanceof JsonSerializerSettingsClass and - p.hasName("TypeNameHandling") and - ( - node1.asExpr() = a.getRValue() and - node2.asExpr() = pw.getQualifier() - or - exists(ObjectInitializer oi | - node1.asExpr() = oi.getAMemberInitializer().getRValue() and - node2.asExpr() = oi - ) - ) - ) - } - } - - /** - * User input to static method or constructor call deserialization flow tracking. - */ - class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration { - TaintToConstructorOrStaticMethodTrackingConfig() { - this = "TaintToConstructorOrStaticMethodTrackingConfig" - } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof ConstructorOrStaticMethodSink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } - - /** - * User input to instance type flow tracking. - */ - class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration { - TaintToObjectTypeTrackingConfig() { this = "TaintToObjectTypeTrackingConfig" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc | - mc.getTarget() instanceof UnsafeDeserializer and - sink.asExpr() = mc.getQualifier() - ) - } - - override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - m.getDeclaringType().hasQualifiedName("System.Type") and - m.hasName("GetType") and - m.isStatic() and - n1.asExpr() = mc.getArgument(0) and - n2.asExpr() = mc - ) - or - exists(ObjectCreation oc | - n1.asExpr() = oc.getAnArgument() and - n2.asExpr() = oc and - oc.getObjectType() instanceof StrongTypeDeserializer - ) - } - } - - /** - * Unsafe deserializer creation to usage tracking config. - */ - class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuration { - WeakTypeCreationToUsageTrackingConfig() { this = "DeserializerCreationToUsageTrackingConfig" } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc.getObjectType() instanceof WeakTypeDeserializer and - source.asExpr() = oc - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc | - mc.getTarget() instanceof UnsafeDeserializer and - sink.asExpr() = mc.getQualifier() - ) - } - } - - /** - * Safe deserializer creation to usage tracking config. - */ - abstract class SafeConstructorTrackingConfig extends TaintTracking2::Configuration { - bindingset[this] - SafeConstructorTrackingConfig() { any() } - } - - /** BinaryFormatter */ - private predicate isBinaryFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - not mc.getArgument(0).hasValue() and - ( - m instanceof BinaryFormatterDeserializeMethod - or - m instanceof BinaryFormatterUnsafeDeserializeMethod - or - m instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod - ) - ) - } - - abstract private class BinaryFormatterSink extends InstanceMethodSink { } - - private class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { - BinaryFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isBinaryFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** SoapFormatter */ - private predicate isSoapFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof SoapFormatterDeserializeMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class SoapFormatterSink extends InstanceMethodSink { } - - private class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { - SoapFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isSoapFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** ObjectStateFormatter */ - private predicate isObjectStateFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof ObjectStateFormatterDeserializeMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class ObjectStateFormatterSink extends InstanceMethodSink { } - - private class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { - ObjectStateFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isObjectStateFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** NetDataContractSerializer */ - private predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - ( - m instanceof NetDataContractSerializerDeserializeMethod - or - m instanceof NetDataContractSerializerReadObjectMethod - ) and - not mc.getArgument(0).hasValue() - ) - } - - abstract private class NetDataContractSerializerSink extends InstanceMethodSink { } - - private class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { - NetDataContractSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isNetDataContractSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** DataContractJsonSerializer */ - private predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof DataContractJsonSerializerReadObjectMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class DataContractJsonSerializerSink extends InstanceMethodSink { } - - private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { - DataContractJsonSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isDataContractJsonSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - DataContractJsonSafeConstructorTrackingConfiguration() { - this = "DataContractJsonSafeConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(Constructor c | - c = oc.getTarget() and - c.getDeclaringType() instanceof DataContractJsonSerializerClass and - c.getNumberOfParameters() > 0 and - oc.getArgument(0) instanceof TypeofExpr - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isDataContractJsonSerializerCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** JavaScriptSerializer */ - private predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - ( - m instanceof JavaScriptSerializerClassDeserializeMethod - or - m instanceof JavaScriptSerializerClassDeserializeObjectMethod - ) and - not mc.getArgument(0).hasValue() - ) - } - - abstract private class JavaScriptSerializerSink extends InstanceMethodSink { } - - private class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { - JavaScriptSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isJavaScriptSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - JavaScriptSerializerSafeConstructorTrackingConfiguration() { - this = "JavaScriptSerializerSafeConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(Constructor c | - c = oc.getTarget() and - c.getDeclaringType() instanceof JavaScriptSerializerClass and - c.getNumberOfParameters() = 0 - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isJavaScriptSerializerCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** XmlObjectSerializer */ - private predicate isXmlObjectSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof XmlObjectSerializerReadObjectMethod and - not mc.getArgument(0).hasValue() and - not mc.targetIsLocalInstance() - } - - abstract private class XmlObjectSerializerSink extends InstanceMethodSink { } - - private class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { - XmlObjectSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isXmlObjectSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - XmlObjectSerializerDerivedConstructorTrackingConfiguration() { - this = "XmlObjectSerializerDerivedConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(ValueOrRefType declaringType | - declaringType = oc.getTarget().getDeclaringType() and - declaringType.getABaseType+() instanceof XmlObjectSerializerClass and - not ( - declaringType instanceof DataContractSerializerClass or - declaringType instanceof NetDataContractSerializerClass - ) - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isXmlObjectSerializerCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** XmlSerializer */ - private predicate isXmlSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof XmlSerializerDeserializeMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class XmlSerializerSink extends InstanceMethodSink { } - - private class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { - XmlSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isXmlSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - XmlSerializerSafeConstructorTrackingConfiguration() { - this = "XmlSerializerSafeConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(Constructor c | - c = oc.getTarget() and - c.getDeclaringType() instanceof XmlSerializerClass and - c.getNumberOfParameters() > 0 and - oc.getArgument(0) instanceof TypeofExpr - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isXmlSerializerCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** DataContractSerializer */ - private predicate isDataContractSerializerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - m instanceof DataContractSerializerReadObjectMethod - or - m instanceof XmlObjectSerializerReadObjectMethod - ) and - not mc.getArgument(0).hasValue() - } - - abstract private class DataContractSerializerSink extends InstanceMethodSink { } - - private class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { - DataContractSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isDataContractSerializerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - DataContractSerializerSafeConstructorTrackingConfiguration() { - this = "DataContractSerializerSafeConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(Constructor c | - c = oc.getTarget() and - c.getDeclaringType() instanceof DataContractSerializerClass and - c.getNumberOfParameters() > 0 and - oc.getArgument(0) instanceof TypeofExpr - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isDataContractSerializerCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** XmlMessageFormatter */ - private predicate isXmlMessageFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof XmlMessageFormatterReadMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class XmlMessageFormatterSink extends InstanceMethodSink { } - - private class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { - XmlMessageFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isXmlMessageFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { - XmlMessageFormatterSafeConstructorTrackingConfiguration() { - this = "XmlMessageFormatterSafeConstructorTrackingConfiguration" - } - - override predicate isSource(DataFlow::Node source) { - exists(ObjectCreation oc | - oc = source.asExpr() and - exists(Constructor c | - c = oc.getTarget() and - c.getDeclaringType() instanceof XmlMessageFormatterClass and - c.getNumberOfParameters() > 0 and - oc.getArgument(0) instanceof TypeofExpr - ) - ) - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodCall mc, Method m | - isXmlMessageFormatterCall(mc, m) and - mc.getQualifier() = sink.asExpr() - ) - } - } - - /** LosFormatter */ - private predicate isLosFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof LosFormatterDeserializeMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class LosFormatterSink extends InstanceMethodSink { } - - private class LosFormatterDeserializeMethodSink extends LosFormatterSink { - LosFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isLosFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** fastJSON */ - private predicate isFastJsonCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof FastJsonClassToObjectMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class FastJsonSink extends ConstructorOrStaticMethodSink { } - - private class FastJsonDeserializeMethodSink extends FastJsonSink { - FastJsonDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isFastJsonCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** Activity */ - private predicate isActivityCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof ActivityLoadMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class ActivitySink extends InstanceMethodSink { } - - private class ActivityDeserializeMethodSink extends ActivitySink { - ActivityDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isActivityCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** ResourceReader */ - private predicate isResourceReaderCall(Call mc, Constructor m) { - m = mc.getTarget() and - m instanceof ResourceReaderConstructor and - not mc.getArgument(0).hasValue() - } - - abstract private class ResourceReaderSink extends ConstructorOrStaticMethodSink { } - - private class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { - ResourceReaderDeserializeMethodSink() { - exists(Call mc, Constructor m | - isResourceReaderCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** BinaryMessageFormatter */ - private predicate isBinaryMessageFormatterCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof BinaryMessageFormatterReadMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class BinaryMessageFormatterSink extends InstanceMethodSink { } - - private class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { - BinaryMessageFormatterDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isBinaryMessageFormatterCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** XamlReader */ - private predicate isXamlReaderCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - m instanceof XamlReaderParseMethod - or - m instanceof XamlReaderLoadMethod - or - m instanceof XamlReaderLoadAsyncMethod - ) and - not mc.getArgument(0).hasValue() - } - - abstract private class XamlReaderSink extends ConstructorOrStaticMethodSink { } - - private class XamlReaderDeserializeMethodSink extends XamlReaderSink { - XamlReaderDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isXamlReaderCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** ProxyObject */ - private predicate isProxyObjectCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - m instanceof ProxyObjectDecodeValueMethod - or - m instanceof ProxyObjectDecodeSerializedObjectMethod - ) and - not mc.getArgument(0).hasValue() - } - - abstract private class ProxyObjectSink extends InstanceMethodSink { } - - private class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { - ProxyObjectDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isProxyObjectCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** SweetJayson */ - private predicate isSweetJaysonCall(MethodCall mc, Method m) { - m = mc.getTarget() and - m instanceof JaysonConverterToObjectMethod and - not mc.getArgument(0).hasValue() - } - - abstract private class SweetJaysonSink extends ConstructorOrStaticMethodSink { } - - private class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { - SweetJaysonDeserializeMethodSink() { - exists(MethodCall mc, Method m | - isSweetJaysonCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** ServiceStack.Text.JsonSerializer */ - abstract private class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { - } - - private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { - ServiceStackTextJsonSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - m instanceof ServiceStackTextJsonSerializerDeserializeFromStringMethod - or - m instanceof ServiceStackTextJsonSerializerDeserializeFromReaderMethod - or - m instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod - ) and - exists(Expr arg | - arg = mc.getAnArgument() and - not arg.hasValue() and - not arg instanceof TypeofExpr and - this.asExpr() = arg - ) - ) - } - } - - /** ServiceStack.Text.TypeSerializer */ - abstract private class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { - } - - private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { - ServiceStackTextTypeSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - m instanceof ServiceStackTextTypeSerializerDeserializeFromStringMethod - or - m instanceof ServiceStackTextTypeSerializerDeserializeFromReaderMethod - or - m instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod - ) and - exists(Expr arg | - arg = mc.getAnArgument() and - not arg.hasValue() and - not arg instanceof TypeofExpr and - this.asExpr() = arg - ) - ) - } - } - - /** ServiceStack.Text.CsvSerializer */ - abstract private class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } - - private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { - ServiceStackTextCsvSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - m instanceof ServiceStackTextCsvSerializerDeserializeFromStringMethod - or - m instanceof ServiceStackTextCsvSerializerDeserializeFromReaderMethod - or - m instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod - ) and - exists(Expr arg | - arg = mc.getAnArgument() and - not arg.hasValue() and - not arg instanceof TypeofExpr and - this.asExpr() = arg - ) - ) - } - } - - /** ServiceStack.Text.XmlSerializer */ - abstract private class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } - - private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { - ServiceStackTextXmlSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - m instanceof ServiceStackTextXmlSerializerDeserializeFromStringMethod - or - m instanceof ServiceStackTextXmlSerializerDeserializeFromReaderMethod - or - m instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod - ) and - exists(Expr arg | - arg = mc.getAnArgument() and - not arg.hasValue() and - not arg instanceof TypeofExpr and - this.asExpr() = arg - ) - ) - } - } - - /** FsPickler */ - private predicate isWeakTypeFsPicklerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - m instanceof FsPicklerSerializerClassUnPickleUntypedMethod or - m instanceof FsPicklerSerializerClassDeserializeUntypedMethod or - m instanceof FsPicklerSerializerClassDeserializeSequenceUntypedMethod - ) and - not mc.getArgument(0).hasValue() - } - - abstract private class FsPicklerWeakTypeSink extends ConstructorOrStaticMethodSink { } - - private class FsPicklerDeserializeWeakTypeMethodSink extends FsPicklerWeakTypeSink { - FsPicklerDeserializeWeakTypeMethodSink() { - exists(MethodCall mc, Method m | - isWeakTypeFsPicklerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - private predicate isStrongTypeFsPicklerCall(MethodCall mc, Method m) { - m = mc.getTarget() and - ( - m instanceof FsPicklerSerializerClassDeserializeMethod or - m instanceof FsPicklerSerializerClassDeserializeSequenceMethod or - m instanceof FsPicklerSerializerClasDeserializeSiftedMethod or - m instanceof FsPicklerSerializerClassUnPickleMethod or - m instanceof FsPicklerSerializerClassUnPickleSiftedMethod or - m instanceof CsPicklerSerializerClassDeserializeMethod or - m instanceof CsPicklerSerializerClassUnPickleMethod or - m instanceof CsPicklerSerializerClassUnPickleOfStringMethod - ) and - not mc.getArgument(0).hasValue() - } - - abstract private class FsPicklerStrongTypeSink extends InstanceMethodSink { } - - private class FsPicklerDeserializeStrongTypeMethodSink extends FsPicklerStrongTypeSink { - FsPicklerDeserializeStrongTypeMethodSink() { - exists(MethodCall mc, Method m | - isStrongTypeFsPicklerCall(mc, m) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** SharpSerializer */ - private class SharpSerializerDeserializeMethodSink extends InstanceMethodSink { - SharpSerializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - not mc.getArgument(0).hasValue() and - m instanceof SharpSerializerClassDeserializeMethod - ) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** YamlDotNet */ - private class YamlDotNetDeserializerDeserializeMethodSink extends ConstructorOrStaticMethodSink { - YamlDotNetDeserializerDeserializeMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - not mc.getArgument(0).hasValue() and - m instanceof YamlDotNetDeserializerClasseserializeMethod - ) and - this.asExpr() = mc.getArgument(0) - ) - } - } - - /** Newtonsoft.Json.JsonConvert */ - private class NewtonsoftJsonConvertDeserializeObjectMethodSink extends ConstructorOrStaticMethodSink { - NewtonsoftJsonConvertDeserializeObjectMethodSink() { - exists(MethodCall mc, Method m | - m = mc.getTarget() and - ( - not mc.getArgument(0).hasValue() and - m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod - ) and - this.asExpr() = mc.getArgument(0) - ) - } - } -} diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll index 7d710575ce2..f7bab643985 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll @@ -4,8 +4,9 @@ */ import csharp -private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers +private import semmle.code.csharp.dataflow.TaintTracking2 +private import semmle.code.csharp.security.dataflow.flowsources.Remote /** * A data flow source for unsafe deserialization vulnerabilities. @@ -17,63 +18,886 @@ abstract class Source extends DataFlow::Node { } */ abstract class Sink extends DataFlow::Node { } +/** + * A data flow sink for unsafe deserialization vulnerabilities to an instance method. + */ +abstract private class InstanceMethodSink extends Sink { + InstanceMethodSink() { + not exists( + SafeConstructorTrackingConfig safeConstructorTracking, DataFlow::Node safeTypeUsage, + MethodCall mc + | + safeConstructorTracking.hasFlow(_, safeTypeUsage) and + mc.getQualifier() = safeTypeUsage.asExpr() and + mc.getAnArgument() = this.asExpr() + ) + } +} + +/** + * A data flow sink for unsafe deserialization vulnerabilities to a static method or constructor call. + */ +abstract private class ConstructorOrStaticMethodSink extends Sink { } + /** * A sanitizer for unsafe deserialization vulnerabilities. */ abstract class Sanitizer extends DataFlow::Node { } -/** - * A taint-tracking configuration for reasoning about unsafe deserialization. - */ -class TaintTrackingConfig extends TaintTracking::Configuration { - TaintTrackingConfig() { this = "UnsafeDeserialization" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } -} - private class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } -/** A call to an unsafe deserializer. */ -private class UnsafeDeserializerSink extends Sink { - UnsafeDeserializerSink() { - exists(Call c | - this.asExpr() = c.getAnArgument() and - c.getTarget() instanceof UnsafeDeserializer - ) - } -} +/** + * User input to object method call deserialization flow tracking. + */ +class TaintToObjectMethodTrackingConfig extends TaintTracking::Configuration { + TaintToObjectMethodTrackingConfig() { this = "TaintToObjectMethodTrackingConfig" } -private class JavaScriptSerializerClass extends Class { - JavaScriptSerializerClass() { - this.hasQualifiedName("System.Web.Script.Serialization.JavaScriptSerializer") - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof InstanceMethodSink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** - * An unsafe use of a JavaScript deserializer. That is, a use with a custom type-resolver - * (constructor parameter). + * User input to `JsonConvert` call deserialization flow tracking. */ -private class JavaScriptSerializerSink extends Sink { - JavaScriptSerializerSink() { - exists(ObjectCreation oc | - oc.getTarget().getDeclaringType() instanceof JavaScriptSerializerClass and - oc.getTarget().getNumberOfParameters() > 0 and - exists(MethodCall mc, Method m | - m = mc.getTarget() and - m.getDeclaringType() instanceof JavaScriptSerializerClass and - ( - m.hasName("Deserialize") or - m.hasName("DeserializeObject") - ) and - this.asExpr() = mc.getAnArgument() and - DataFlow::localFlow(DataFlow::exprNode(oc), DataFlow::exprNode(mc.getQualifier())) +class JsonConvertTrackingConfig extends TaintTracking::Configuration { + JsonConvertTrackingConfig() { this = "JsonConvertTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof NewtonsoftJsonConvertDeserializeObjectMethodSink + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * Tracks unsafe `TypeNameHandling` setting to `JsonConvert` call + */ +class TypeNameTrackingConfig extends DataFlow::Configuration { + TypeNameTrackingConfig() { this = "TypeNameTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { + ( + source.asExpr() instanceof MemberConstantAccess and + source.getType() instanceof TypeNameHandlingEnum + or + source.asExpr() instanceof IntegerLiteral + ) and + source.asExpr().hasValue() and + not source.asExpr().getValue() = "0" + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m, Expr expr | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod + ) and + expr = mc.getAnArgument() and + sink.asExpr() = expr and + expr.getType() instanceof JsonSerializerSettingsClass + ) + } + + override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.asExpr() instanceof IntegerLiteral and + node2.asExpr().(CastExpr).getExpr() = node1.asExpr() + or + node1.getType() instanceof TypeNameHandlingEnum and + exists(PropertyWrite pw, Property p, Assignment a | + a.getLValue() = pw and + pw.getProperty() = p and + p.getDeclaringType() instanceof JsonSerializerSettingsClass and + p.hasName("TypeNameHandling") and + ( + node1.asExpr() = a.getRValue() and + node2.asExpr() = pw.getQualifier() + or + exists(ObjectInitializer oi | + node1.asExpr() = oi.getAMemberInitializer().getRValue() and + node2.asExpr() = oi + ) ) ) } } + +/** + * User input to static method or constructor call deserialization flow tracking. + */ +class TaintToConstructorOrStaticMethodTrackingConfig extends TaintTracking::Configuration { + TaintToConstructorOrStaticMethodTrackingConfig() { + this = "TaintToConstructorOrStaticMethodTrackingConfig" + } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof ConstructorOrStaticMethodSink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * User input to instance type flow tracking. + */ +class TaintToObjectTypeTrackingConfig extends TaintTracking2::Configuration { + TaintToObjectTypeTrackingConfig() { this = "TaintToObjectTypeTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget() instanceof UnsafeDeserializer and + sink.asExpr() = mc.getQualifier() + ) + } + + override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + m.getDeclaringType().hasQualifiedName("System.Type") and + m.hasName("GetType") and + m.isStatic() and + n1.asExpr() = mc.getArgument(0) and + n2.asExpr() = mc + ) + or + exists(ObjectCreation oc | + n1.asExpr() = oc.getAnArgument() and + n2.asExpr() = oc and + oc.getObjectType() instanceof StrongTypeDeserializer + ) + } +} + +/** + * Unsafe deserializer creation to usage tracking config. + */ +class WeakTypeCreationToUsageTrackingConfig extends TaintTracking2::Configuration { + WeakTypeCreationToUsageTrackingConfig() { this = "DeserializerCreationToUsageTrackingConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc.getObjectType() instanceof WeakTypeDeserializer and + source.asExpr() = oc + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget() instanceof UnsafeDeserializer and + sink.asExpr() = mc.getQualifier() + ) + } +} + +/** + * Safe deserializer creation to usage tracking config. + */ +abstract class SafeConstructorTrackingConfig extends TaintTracking2::Configuration { + bindingset[this] + SafeConstructorTrackingConfig() { any() } +} + +/** BinaryFormatter */ +private predicate isBinaryFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + ( + m instanceof BinaryFormatterDeserializeMethod + or + m instanceof BinaryFormatterUnsafeDeserializeMethod + or + m instanceof BinaryFormatterUnsafeDeserializeMethodResponseMethod + ) + ) +} + +abstract private class BinaryFormatterSink extends InstanceMethodSink { } + +private class BinaryFormatterDeserializeMethodSink extends BinaryFormatterSink { + BinaryFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isBinaryFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** SoapFormatter */ +private predicate isSoapFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof SoapFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class SoapFormatterSink extends InstanceMethodSink { } + +private class SoapFormatterDeserializeMethodSink extends SoapFormatterSink { + SoapFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isSoapFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** ObjectStateFormatter */ +private predicate isObjectStateFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof ObjectStateFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class ObjectStateFormatterSink extends InstanceMethodSink { } + +private class ObjectStateFormatterDeserializeMethodSink extends ObjectStateFormatterSink { + ObjectStateFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isObjectStateFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** NetDataContractSerializer */ +private predicate isNetDataContractSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + ( + m instanceof NetDataContractSerializerDeserializeMethod + or + m instanceof NetDataContractSerializerReadObjectMethod + ) and + not mc.getArgument(0).hasValue() + ) +} + +abstract private class NetDataContractSerializerSink extends InstanceMethodSink { } + +private class NetDataContractSerializerDeserializeMethodSink extends NetDataContractSerializerSink { + NetDataContractSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isNetDataContractSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** DataContractJsonSerializer */ +private predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof DataContractJsonSerializerReadObjectMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class DataContractJsonSerializerSink extends InstanceMethodSink { } + +private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { + DataContractJsonSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isDataContractJsonSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + DataContractJsonSafeConstructorTrackingConfiguration() { + this = "DataContractJsonSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof DataContractJsonSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isDataContractJsonSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** JavaScriptSerializer */ +private predicate isJavaScriptSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + ( + m instanceof JavaScriptSerializerClassDeserializeMethod + or + m instanceof JavaScriptSerializerClassDeserializeObjectMethod + ) and + not mc.getArgument(0).hasValue() + ) +} + +abstract private class JavaScriptSerializerSink extends InstanceMethodSink { } + +private class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerializerSink { + JavaScriptSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isJavaScriptSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + JavaScriptSerializerSafeConstructorTrackingConfiguration() { + this = "JavaScriptSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof JavaScriptSerializerClass and + c.getNumberOfParameters() = 0 + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isJavaScriptSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** XmlObjectSerializer */ +private predicate isXmlObjectSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlObjectSerializerReadObjectMethod and + not mc.getArgument(0).hasValue() and + not mc.targetIsLocalInstance() +} + +abstract private class XmlObjectSerializerSink extends InstanceMethodSink { } + +private class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializerSink { + XmlObjectSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlObjectSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlObjectSerializerDerivedConstructorTrackingConfiguration() { + this = "XmlObjectSerializerDerivedConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(ValueOrRefType declaringType | + declaringType = oc.getTarget().getDeclaringType() and + declaringType.getABaseType+() instanceof XmlObjectSerializerClass and + not ( + declaringType instanceof DataContractSerializerClass or + declaringType instanceof NetDataContractSerializerClass + ) + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlObjectSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** XmlSerializer */ +private predicate isXmlSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlSerializerDeserializeMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class XmlSerializerSink extends InstanceMethodSink { } + +private class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { + XmlSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlSerializerSafeConstructorTrackingConfiguration() { + this = "XmlSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof XmlSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** DataContractSerializer */ +private predicate isDataContractSerializerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof DataContractSerializerReadObjectMethod + or + m instanceof XmlObjectSerializerReadObjectMethod + ) and + not mc.getArgument(0).hasValue() +} + +abstract private class DataContractSerializerSink extends InstanceMethodSink { } + +private class DataContractSerializerDeserializeMethodSink extends DataContractSerializerSink { + DataContractSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isDataContractSerializerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + DataContractSerializerSafeConstructorTrackingConfiguration() { + this = "DataContractSerializerSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof DataContractSerializerClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isDataContractSerializerCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** XmlMessageFormatter */ +private predicate isXmlMessageFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof XmlMessageFormatterReadMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class XmlMessageFormatterSink extends InstanceMethodSink { } + +private class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatterSink { + XmlMessageFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXmlMessageFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { + XmlMessageFormatterSafeConstructorTrackingConfiguration() { + this = "XmlMessageFormatterSafeConstructorTrackingConfiguration" + } + + override predicate isSource(DataFlow::Node source) { + exists(ObjectCreation oc | + oc = source.asExpr() and + exists(Constructor c | + c = oc.getTarget() and + c.getDeclaringType() instanceof XmlMessageFormatterClass and + c.getNumberOfParameters() > 0 and + oc.getArgument(0) instanceof TypeofExpr + ) + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc, Method m | + isXmlMessageFormatterCall(mc, m) and + mc.getQualifier() = sink.asExpr() + ) + } +} + +/** LosFormatter */ +private predicate isLosFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof LosFormatterDeserializeMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class LosFormatterSink extends InstanceMethodSink { } + +private class LosFormatterDeserializeMethodSink extends LosFormatterSink { + LosFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isLosFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** fastJSON */ +private predicate isFastJsonCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof FastJsonClassToObjectMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class FastJsonSink extends ConstructorOrStaticMethodSink { } + +private class FastJsonDeserializeMethodSink extends FastJsonSink { + FastJsonDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isFastJsonCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** Activity */ +private predicate isActivityCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof ActivityLoadMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class ActivitySink extends InstanceMethodSink { } + +private class ActivityDeserializeMethodSink extends ActivitySink { + ActivityDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isActivityCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** ResourceReader */ +private predicate isResourceReaderCall(Call mc, Constructor m) { + m = mc.getTarget() and + m instanceof ResourceReaderConstructor and + not mc.getArgument(0).hasValue() +} + +abstract private class ResourceReaderSink extends ConstructorOrStaticMethodSink { } + +private class ResourceReaderDeserializeMethodSink extends ResourceReaderSink { + ResourceReaderDeserializeMethodSink() { + exists(Call mc, Constructor m | + isResourceReaderCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** BinaryMessageFormatter */ +private predicate isBinaryMessageFormatterCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof BinaryMessageFormatterReadMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class BinaryMessageFormatterSink extends InstanceMethodSink { } + +private class BinaryMessageFormatterDeserializeMethodSink extends BinaryMessageFormatterSink { + BinaryMessageFormatterDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isBinaryMessageFormatterCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** XamlReader */ +private predicate isXamlReaderCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof XamlReaderParseMethod + or + m instanceof XamlReaderLoadMethod + or + m instanceof XamlReaderLoadAsyncMethod + ) and + not mc.getArgument(0).hasValue() +} + +abstract private class XamlReaderSink extends ConstructorOrStaticMethodSink { } + +private class XamlReaderDeserializeMethodSink extends XamlReaderSink { + XamlReaderDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isXamlReaderCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** ProxyObject */ +private predicate isProxyObjectCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof ProxyObjectDecodeValueMethod + or + m instanceof ProxyObjectDecodeSerializedObjectMethod + ) and + not mc.getArgument(0).hasValue() +} + +abstract private class ProxyObjectSink extends InstanceMethodSink { } + +private class ProxyObjectDeserializeMethodSink extends ProxyObjectSink { + ProxyObjectDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isProxyObjectCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** SweetJayson */ +private predicate isSweetJaysonCall(MethodCall mc, Method m) { + m = mc.getTarget() and + m instanceof JaysonConverterToObjectMethod and + not mc.getArgument(0).hasValue() +} + +abstract private class SweetJaysonSink extends ConstructorOrStaticMethodSink { } + +private class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { + SweetJaysonDeserializeMethodSink() { + exists(MethodCall mc, Method m | + isSweetJaysonCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** ServiceStack.Text.JsonSerializer */ +abstract private class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } + +private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { + ServiceStackTextJsonSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextJsonSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextJsonSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextJsonSerializerDeserializeFromStreamMethod + ) and + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) + ) + } +} + +/** ServiceStack.Text.TypeSerializer */ +abstract private class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } + +private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { + ServiceStackTextTypeSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextTypeSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextTypeSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextTypeSerializerDeserializeFromStreamMethod + ) and + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) + ) + } +} + +/** ServiceStack.Text.CsvSerializer */ +abstract private class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } + +private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { + ServiceStackTextCsvSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextCsvSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextCsvSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextCsvSerializerDeserializeFromStreamMethod + ) and + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) + ) + } +} + +/** ServiceStack.Text.XmlSerializer */ +abstract private class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } + +private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { + ServiceStackTextXmlSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + m instanceof ServiceStackTextXmlSerializerDeserializeFromStringMethod + or + m instanceof ServiceStackTextXmlSerializerDeserializeFromReaderMethod + or + m instanceof ServiceStackTextXmlSerializerDeserializeFromStreamMethod + ) and + exists(Expr arg | + arg = mc.getAnArgument() and + not arg.hasValue() and + not arg instanceof TypeofExpr and + this.asExpr() = arg + ) + ) + } +} + +/** FsPickler */ +private predicate isWeakTypeFsPicklerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof FsPicklerSerializerClassUnPickleUntypedMethod or + m instanceof FsPicklerSerializerClassDeserializeUntypedMethod or + m instanceof FsPicklerSerializerClassDeserializeSequenceUntypedMethod + ) and + not mc.getArgument(0).hasValue() +} + +abstract private class FsPicklerWeakTypeSink extends ConstructorOrStaticMethodSink { } + +private class FsPicklerDeserializeWeakTypeMethodSink extends FsPicklerWeakTypeSink { + FsPicklerDeserializeWeakTypeMethodSink() { + exists(MethodCall mc, Method m | + isWeakTypeFsPicklerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +private predicate isStrongTypeFsPicklerCall(MethodCall mc, Method m) { + m = mc.getTarget() and + ( + m instanceof FsPicklerSerializerClassDeserializeMethod or + m instanceof FsPicklerSerializerClassDeserializeSequenceMethod or + m instanceof FsPicklerSerializerClasDeserializeSiftedMethod or + m instanceof FsPicklerSerializerClassUnPickleMethod or + m instanceof FsPicklerSerializerClassUnPickleSiftedMethod or + m instanceof CsPicklerSerializerClassDeserializeMethod or + m instanceof CsPicklerSerializerClassUnPickleMethod or + m instanceof CsPicklerSerializerClassUnPickleOfStringMethod + ) and + not mc.getArgument(0).hasValue() +} + +abstract private class FsPicklerStrongTypeSink extends InstanceMethodSink { } + +private class FsPicklerDeserializeStrongTypeMethodSink extends FsPicklerStrongTypeSink { + FsPicklerDeserializeStrongTypeMethodSink() { + exists(MethodCall mc, Method m | + isStrongTypeFsPicklerCall(mc, m) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** SharpSerializer */ +private class SharpSerializerDeserializeMethodSink extends InstanceMethodSink { + SharpSerializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof SharpSerializerClassDeserializeMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** YamlDotNet */ +private class YamlDotNetDeserializerDeserializeMethodSink extends ConstructorOrStaticMethodSink { + YamlDotNetDeserializerDeserializeMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof YamlDotNetDeserializerClasseserializeMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } +} + +/** Newtonsoft.Json.JsonConvert */ +private class NewtonsoftJsonConvertDeserializeObjectMethodSink extends ConstructorOrStaticMethodSink { + NewtonsoftJsonConvertDeserializeObjectMethodSink() { + exists(MethodCall mc, Method m | + m = mc.getTarget() and + ( + not mc.getArgument(0).hasValue() and + m instanceof NewtonsoftJsonConvertClassDeserializeObjectMethod + ) and + this.asExpr() = mc.getArgument(0) + ) + } +} From 8544356f904e1178e582b9ac32adbaf72acc59ce Mon Sep 17 00:00:00 2001 From: "Raul Garcia (MSFT)" Date: Wed, 4 Aug 2021 17:12:00 -0700 Subject: [PATCH 147/429] Adding `Membership.GeneratePassword()` as a bad source of random data because of the bias. --- csharp/ql/src/Security Features/InsecureRandomness.cs | 2 +- csharp/ql/src/Security Features/InsecureRandomness.ql | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/Security Features/InsecureRandomness.cs b/csharp/ql/src/Security Features/InsecureRandomness.cs index e8dd58dc6ea..750c0cc008f 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.cs +++ b/csharp/ql/src/Security Features/InsecureRandomness.cs @@ -15,7 +15,7 @@ string GeneratePassword() password = "mypassword" + BitConverter.ToInt32(randomBytes); } - // GOOD: Password is generated using a cryptographically secure RNG + // BAD: Membership.GeneratePassword is generates a password with a bias password = Membership.GeneratePassword(12, 3); return password; diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index b618bff07a5..9d8dc5716de 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -59,6 +59,12 @@ module Random { this.getExpr() = any(MethodCall mc | mc.getQualifier().getType().(RefType).hasQualifiedName("System", "Random") + or + // by using `% 87` on a `byte`, this function has a bias + mc.getQualifier() + .getType() + .(RefType) + .hasQualifiedName("System.Web.Security", "GeneratePassword") ) } } From 7340a1293f0e759930455ded6dc50b6d07c0ba95 Mon Sep 17 00:00:00 2001 From: "Raul Garcia (MSFT)" Date: Wed, 4 Aug 2021 19:37:57 -0700 Subject: [PATCH 148/429] Fixing query & test --- .../Security Features/InsecureRandomness.ql | 5 +++-- .../CWE-338/InsecureRandomness.cs | 20 +++++++++++++++++++ .../CWE-338/InsecureRandomness.expected | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index 9d8dc5716de..08b46a41439 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -60,11 +60,12 @@ module Random { any(MethodCall mc | mc.getQualifier().getType().(RefType).hasQualifiedName("System", "Random") or - // by using `% 87` on a `byte`, this function has a bias + // by using `% 87` on a `byte`, `System.Web.Security.Membership.GeneratePassword` has a bias mc.getQualifier() .getType() .(RefType) - .hasQualifiedName("System.Web.Security", "GeneratePassword") + .hasQualifiedName("System.Web.Security", "Membership") and + mc.getTarget().hasName("GeneratePassword") ) } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs index 90718478986..3503bff8f41 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs @@ -73,4 +73,24 @@ public class InsecureRandomness } return result; } + + public static string BiasPasswordGeneration() + { + // BAD: Membership.GeneratePassword is generates a password with a bias + string password = System.Web.Security.Membership.GeneratePassword(12, 3); + return password; + } + +} + +namespace System.Web.Security +{ + public static class Membership + { + public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters) + { + return "stub"; + } + + } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected index 6b2615a85ce..3bfbf2530eb 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.expected @@ -29,7 +29,9 @@ nodes | InsecureRandomness.cs:62:16:62:32 | call to method ToString : String | semmle.label | call to method ToString : String | | InsecureRandomness.cs:72:31:72:39 | call to method Next : Int32 | semmle.label | call to method Next : Int32 | | InsecureRandomness.cs:74:16:74:21 | access to local variable result : String | semmle.label | access to local variable result : String | +| InsecureRandomness.cs:80:28:80:81 | call to method GeneratePassword | semmle.label | call to method GeneratePassword | #select | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | InsecureRandomness.cs:28:29:28:43 | call to method Next : Int32 | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:28:29:28:43 | call to method Next | call to method Next | | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | InsecureRandomness.cs:60:31:60:39 | call to method Next : Int32 | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:60:31:60:39 | call to method Next | call to method Next | | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | InsecureRandomness.cs:72:31:72:39 | call to method Next : Int32 | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:72:31:72:39 | call to method Next | call to method Next | +| InsecureRandomness.cs:80:28:80:81 | call to method GeneratePassword | InsecureRandomness.cs:80:28:80:81 | call to method GeneratePassword | InsecureRandomness.cs:80:28:80:81 | call to method GeneratePassword | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:80:28:80:81 | call to method GeneratePassword | call to method GeneratePassword | From 0b6c991ac4f3c5f0b33ba613b661d88ff17f7540 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 5 Aug 2021 16:01:14 +0100 Subject: [PATCH 149/429] Unsafe deserialization: add support for Jodd JSON library --- .../2021-08-05-jodd-unsafe-deserialization.md | 2 + .../CWE/CWE-502/UnsafeDeserialization.qhelp | 6 +- .../code/java/dataflow/ExternalFlow.qll | 1 + .../semmle/code/java/frameworks/JoddJson.qll | 68 ++++ .../security/UnsafeDeserializationQuery.qll | 106 +++++ .../security/CWE-502/JoddJsonServlet.java | 102 +++++ .../test/query-tests/security/CWE-502/options | 2 +- .../joddjson-6.0.3/jodd/json/JsonArray.java | 293 +++++++++++++ .../joddjson-6.0.3/jodd/json/JsonObject.java | 385 ++++++++++++++++++ .../joddjson-6.0.3/jodd/json/JsonParser.java | 218 ++++++++++ .../jodd/json/JsonParserBase.java | 68 ++++ .../joddjson-6.0.3/jodd/json/MapToBean.java | 45 ++ 12 files changed, 1294 insertions(+), 2 deletions(-) create mode 100644 java/change-notes/2021-08-05-jodd-unsafe-deserialization.md create mode 100644 java/ql/src/semmle/code/java/frameworks/JoddJson.qll create mode 100644 java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java create mode 100644 java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonArray.java create mode 100644 java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonObject.java create mode 100644 java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParser.java create mode 100644 java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParserBase.java create mode 100644 java/ql/test/stubs/joddjson-6.0.3/jodd/json/MapToBean.java diff --git a/java/change-notes/2021-08-05-jodd-unsafe-deserialization.md b/java/change-notes/2021-08-05-jodd-unsafe-deserialization.md new file mode 100644 index 00000000000..cbdde90a065 --- /dev/null +++ b/java/change-notes/2021-08-05-jodd-unsafe-deserialization.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The "Deserialization of user-controlled data" (`java/unsafe-deserialization`) query now recognizes deserialization using the `Jodd JSON` library. diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp index 9c87aae7e37..0e7cfae08d0 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp @@ -15,7 +15,7 @@ may have unforeseen effects, such as the execution of arbitrary code.

    There are many different serialization frameworks. This query currently supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap, -Jackson, Jabsorb and Java IO serialization through +Jackson, Jabsorb, Jodd JSON and Java IO serialization through ObjectInputStream/ObjectOutputStream.

    @@ -105,6 +105,10 @@ Blog posts by the developer of Jackson libraries: Jabsorb documentation on deserialization: Jabsorb JSON Serializer. +
  • +Jodd JSON documentation on deserialization: +JoddJson Parser. +
  • diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll index 3b49289d885..23d3eaf26ba 100644 --- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll @@ -85,6 +85,7 @@ private module Frameworks { private import semmle.code.java.frameworks.jackson.JacksonSerializability private import semmle.code.java.frameworks.JavaxJson private import semmle.code.java.frameworks.JaxWS + private import semmle.code.java.frameworks.JoddJson private import semmle.code.java.frameworks.JsonJava private import semmle.code.java.frameworks.Optional private import semmle.code.java.frameworks.spring.SpringCache diff --git a/java/ql/src/semmle/code/java/frameworks/JoddJson.qll b/java/ql/src/semmle/code/java/frameworks/JoddJson.qll new file mode 100644 index 00000000000..594a353f67b --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/JoddJson.qll @@ -0,0 +1,68 @@ +/** + * Provides classes and predicates for working with the Jodd JSON framework. + */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +/** The class `jodd.json.Parser`. */ +class JoddJsonParser extends RefType { + JoddJsonParser() { this.hasQualifiedName("jodd.json", "JsonParser") } +} + +/** A `JsonParser.parse*` deserialization method. */ +class JoddJsonParseMethod extends Method { + JoddJsonParseMethod() { + this.getDeclaringType() instanceof JoddJsonParser and + this.getName().matches("parse%") + } +} + +/** The `JsonParser.setClassMetadataName` method. */ +class SetClassMetadataNameMethod extends Method { + SetClassMetadataNameMethod() { + this.getDeclaringType() instanceof JoddJsonParser and + this.hasName("setClassMetadataName") + } +} + +/** The `JsonParser.withClassMetadata` method. */ +class WithClassMetadataMethod extends Method { + WithClassMetadataMethod() { + this.getDeclaringType() instanceof JoddJsonParser and + this.hasName("withClassMetadata") + } +} + +/** The `JsonParser.allowClass` method. */ +class AllowClassMethod extends Method { + AllowClassMethod() { + this.getDeclaringType() instanceof JoddJsonParser and + this.hasName("allowClass") + } +} + +/** + * A partial model of jodd.json.JsonParser noting fluent methods. + * + * This means that DataFlow::localFlow and similar methods are aware + * that the result of (e.g.) JsonParser.allowClass is an alias of the + * qualifier. + */ +private class JsonParserFluentMethods extends SummaryModelCsv { + override predicate row(string s) { + s = + [ + "jodd.json;JsonParser;false;allowAllClasses;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;allowClass;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;lazy;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;looseMode;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;map;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;setClassMetadataName;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;strictTypes;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;useAltPaths;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;withClassMetadata;;;Argument[-1];ReturnValue;value", + "jodd.json;JsonParser;false;withValueConverter;;;Argument[-1];ReturnValue;value" + ] + } +} diff --git a/java/ql/src/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserializationQuery.qll index fe58166965c..a45c4e8aa5d 100644 --- a/java/ql/src/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/src/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -15,6 +15,7 @@ private import semmle.code.java.frameworks.HessianBurlap private import semmle.code.java.frameworks.Castor private import semmle.code.java.frameworks.Jackson private import semmle.code.java.frameworks.Jabsorb +private import semmle.code.java.frameworks.JoddJson private import semmle.code.java.frameworks.apache.Lang private import semmle.code.java.Reflection @@ -192,6 +193,16 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { or m instanceof JabsorbFromJsonMethod and sink = ma.getArgument(0) + or + m instanceof JoddJsonParseMethod and + sink = ma.getArgument(0) and + ( + // User controls the target type for deserialization + any(UnsafeTypeConfig c).hasFlowToExpr(ma.getArgument(1)) + or + // jodd.json.JsonParser may be configured for unrestricted deserialization to user-specified types + joddJsonParserConfiguredUnsafely(ma.getQualifier()) + ) ) } @@ -248,6 +259,17 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration { ma.getArgument(0) = node.asExpr() and exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(ma.getArgument(1))) ) + or + exists(MethodAccess ma | + // Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears + // to be called with an explicit class argument limiting those types that can + // be instantiated during deserialization. + ma.getMethod() instanceof JoddJsonParseMethod and + ma.getArgument(1).getType() instanceof TypeClass and + not ma.getArgument(1) instanceof NullLiteral and + not ma.getArgument(1).getType().getName() = ["Class", "Class"] and + node.asExpr() = ma.getAnArgument() + ) } } @@ -295,6 +317,8 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration { ma.getMethod() instanceof ObjectMapperReadMethod or ma.getMethod() instanceof JabsorbUnmarshallMethod + or + ma.getMethod() instanceof JoddJsonParseMethod ) and // Note `JacksonTypeDescriptorType` includes plain old `java.lang.Class` arg.getType() instanceof JacksonTypeDescriptorType and @@ -356,3 +380,85 @@ class SafeObjectMapperConfig extends DataFlow2::Configuration { ) } } + +/** + * A method that configures Jodd's JsonParser, either enabling dangerous deserialization to + * arbitrary Java types or restricting the types that can be instantiated. + */ +private class JoddJsonParserConfigurationMethodQualifier extends DataFlow::ExprNode { + JoddJsonParserConfigurationMethodQualifier() { + exists(MethodAccess ma, Method m | ma.getQualifier() = this.asExpr() and m = ma.getMethod() | + m instanceof WithClassMetadataMethod + or + m instanceof SetClassMetadataNameMethod + or + m instanceof AllowClassMethod + ) + } +} + +/** + * Configuration tracking flow from methods that configure `jodd.json.JsonParser`'s class + * instantiation feature to a `.parse` call on the same parser. + */ +private class JoddJsonParserConfigurationMethodConfig extends DataFlow2::Configuration { + JoddJsonParserConfigurationMethodConfig() { + this = "UnsafeDeserialization::JoddJsonParserConfigurationMethodConfig" + } + + override predicate isSource(DataFlow::Node src) { + src instanceof JoddJsonParserConfigurationMethodQualifier + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof JoddJsonParseMethod and + sink.asExpr() = ma.getQualifier() // The class type argument + ) + } +} + +/** + * Gets the qualifier to a method call that configures a `jodd.json.JsonParser` instance unsafely. + * + * Such a parser may instantiate an arbtirary type when deserializing untrusted data. + */ +private DataFlow::Node getAnUnsafelyConfiguredParser() { + exists(MethodAccess ma | result.asExpr() = ma.getQualifier() | + ma.getMethod() instanceof WithClassMetadataMethod and + ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = true + or + ma.getMethod() instanceof SetClassMetadataNameMethod and + not ma.getArgument(0) instanceof NullLiteral + ) +} + +/** + * Gets the qualifier to a method call that configures a `jodd.json.JsonParser` instance safely. + * + * Such a parser will not instantiate an arbtirary type when deserializing untrusted data. + */ +private DataFlow::Node getASafelyConfiguredParser() { + exists(MethodAccess ma | result.asExpr() = ma.getQualifier() | + ma.getMethod() instanceof WithClassMetadataMethod and + ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false + or + ma.getMethod() instanceof SetClassMetadataNameMethod and + ma.getArgument(0) instanceof NullLiteral + or + ma.getMethod() instanceof AllowClassMethod + ) +} + +/** + * Holds if `parseMethodQualifierExpr` is a `jodd.json.JsonParser` instance that is configured unsafely + * and which never appears to be configured safely. + */ +private predicate joddJsonParserConfiguredUnsafely(Expr parserExpr) { + exists(DataFlow::Node parser, JoddJsonParserConfigurationMethodConfig config | + parser.asExpr() = parserExpr + | + config.hasFlow(getAnUnsafelyConfiguredParser(), parser) and + not config.hasFlow(getASafelyConfiguredParser(), parser) + ) +} diff --git a/java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java b/java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java new file mode 100644 index 00000000000..c10bfbc46b9 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-502/JoddJsonServlet.java @@ -0,0 +1,102 @@ +import java.io.IOException; +import java.io.Reader; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import jodd.json.JsonParser; + +import com.example.User; +import com.thirdparty.Person; + +public class JoddJsonServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + // GOOD: class type specified (despite a dangerous configuration) + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + + JsonParser parser = new JsonParser(); + parser.setClassMetadataName("class"); + Person person = parser.parse(json, Person.class); + } + + @Override + // BAD: dangerously configured parser with no class restriction passed to `parse`, + // using a few different possible call sequences. + public void doHead(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + int callOrder; + try { + callOrder = Integer.parseInt(req.getParameter("callOrder")); + } + catch(NumberFormatException e) { + throw new RuntimeException(e); + } + + JsonParser parser = new JsonParser(); + if(callOrder == 0) { + parser.setClassMetadataName("class"); + User obj = parser.parse(json, null); // $unsafeDeserialization + } else if(callOrder == 1) { + parser.setClassMetadataName("class").parse(json, null); // $unsafeDeserialization + } else if(callOrder == 2) { + parser.setClassMetadataName("class").lazy(true).parse(json, null); // $unsafeDeserialization + } else if(callOrder == 3) { + parser.withClassMetadata(true).lazy(true).parse(json, null); // $unsafeDeserialization + } + } + + @Override + // BAD: allow class name to be controlled by remote source + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + + try { + JsonParser parser = new JsonParser(); + Object obj = parser.parse(json, Class.forName(clazz)); // $unsafeDeserialization + } catch (ClassNotFoundException cne) { + throw new IOException(cne.getMessage()); + } + } + + @Override + // GOOD: dangerously configured parser is ameliorated by setting a list of allowed classes, using various call orders, + // or by explicitly disabling the class metadata option. + public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String json = req.getParameter("json"); + String clazz = req.getParameter("class"); + int callOrder; + try { + callOrder = Integer.parseInt(req.getParameter("callOrder")); + } + catch(NumberFormatException e) { + throw new RuntimeException(e); + } + + JsonParser parser = new JsonParser(); + if(callOrder == 0) { + parser.setClassMetadataName("class"); + parser.allowClass("example.Class"); + User obj = parser.parse(json, null); + } else if(callOrder == 1) { + parser.allowClass("example.Class"); + parser.setClassMetadataName("class"); + User obj = parser.parse(json, null); + } else if(callOrder == 2) { + parser.setClassMetadataName("class").allowClass("example.Class").parse(json, null); + } else if(callOrder == 3) { + parser.allowClass("example.Class").setClassMetadataName("class").parse(json, null); + } else if(callOrder == 4) { + parser.setClassMetadataName("class").withClassMetadata(false).parse(json, null); + } else if(callOrder == 5) { + parser.withClassMetadata(true).setClassMetadataName(null).parse(json, null); + } + } +} \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-502/options b/java/ql/test/query-tests/security/CWE-502/options index e3f830b52fc..79476eded38 100644 --- a/java/ql/test/query-tests/security/CWE-502/options +++ b/java/ql/test/query-tests/security/CWE-502/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/snakeyaml-1.21:${testdir}/../../../stubs/xstream-1.4.10:${testdir}/../../../stubs/kryo-4.0.2:${testdir}/../../../stubs/jsr311-api-1.1.1:${testdir}/../../../stubs/fastjson-1.2.74:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/jyaml-1.3:${testdir}/../../../stubs/json-io-4.10.0:${testdir}/../../../stubs/yamlbeans-1.09:${testdir}/../../../stubs/hessian-4.0.38:${testdir}/../../../stubs/castor-1.4.1:${testdir}/../../../stubs/jackson-databind-2.12:${testdir}/../../../stubs/jackson-core-2.12:${testdir}/../../../stubs/jabsorb-1.3.2:${testdir}/../../../stubs/json-java-20210307:${testdir}/../../../stubs/joddjson-6.0.3 diff --git a/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonArray.java b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonArray.java new file mode 100644 index 00000000000..e86747fc8c5 --- /dev/null +++ b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonArray.java @@ -0,0 +1,293 @@ +// Copyright (c) 2003-present, Jodd Team (http://jodd.org) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package jodd.json; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Representation of JSON array. + * @see JsonObject + */ +public class JsonArray implements Iterable { + + /** + * Creates an empty instance. + */ + public JsonArray() { + } + + /** + * Creates an instance from a List. The List is not copied. + */ + public JsonArray(final List list) { + } + + // ---------------------------------------------------------------- get + + /** + * Returns the string at position {@code pos} in the array. + */ + public String getString(final int pos) { + return null; + } + + /** + * Returns the integer at position {@code pos} in the array. + */ + public Integer getInteger(final int pos) { + return null; + } + + /** + * Returns the long at position {@code pos} in the array. + */ + public Long getLong(final int pos) { + return null; + } + + /** + * Returns the double at position {@code pos} in the array. + */ + public Double getDouble(final int pos) { + return null; + } + + /** + * Returns the Float at position {@code pos} in the array. + */ + public Float getFloat(final int pos) { + return null; + } + + /** + * Returns the boolean at position {@code pos} in the array. + */ + public Boolean getBoolean(final int pos) { + return null; + } + + /** + * Returns the JsonObject at position {@code pos} in the array. + */ + public JsonObject getJsonObject(final int pos) { + return null; + } + + /** + * Returns the JsonArray at position {@code pos} in the array. + */ + public JsonArray getJsonArray(final int pos) { + return null; + } + + /** + * Returns the byte[] at position {@code pos} in the array. + *

    + * JSON itself has no notion of a binary, so this method assumes there is a String value and + * it contains a Base64 encoded binary, which it decodes if found and returns. + */ + public byte[] getBinary(final int pos) { + return null; + } + + /** + * Returns the object value at position {@code pos} in the array. + */ + public Object getValue(final int pos) { + return null; + } + + /** + * Returns {@code true} if there is a {@code null} value at given index. + */ + public boolean hasNull(final int pos) { + return false; + } + + /** + * Adds an enum to the JSON array. + *

    + * JSON has no concept of encoding Enums, so the Enum will be converted to a String using the {@link java.lang.Enum#name} + * method and the value added as a String. + */ + public JsonArray add(final Enum value) { + return null; + } + + /** + * Adds a {@code CharSequence} to the JSON array. + */ + public JsonArray add(final CharSequence value) { + return null; + } + + /** + * Adds a string to the JSON array. + */ + public JsonArray add(final String value) { + return null; + } + + /** + * Adds an integer to the JSON array. + */ + public JsonArray add(final Integer value) { + return null; + } + + /** + * Adds a long to the JSON array. + */ + public JsonArray add(final Long value) { + return null; + } + + /** + * Adds a double to the JSON array. + */ + public JsonArray add(final Double value) { + return null; + } + + /** + * Adds a float to the JSON array. + */ + public JsonArray add(final Float value) { + return null; + } + + /** + * Adds a boolean to the JSON array. + */ + public JsonArray add(final Boolean value) { + return null; + } + + /** + * Adds a {@code null} value to the JSON array. + */ + public JsonArray addNull() { + return null; + } + + /** + * Adds a JSON object to the JSON array. + */ + public JsonArray add(final JsonObject value) { + return null; + } + + /** + * Adds another JSON array to the JSON array. + */ + public JsonArray add(final JsonArray value) { + return null; + } + + /** + * Adds a binary value to the JSON array. + *

    + * JSON has no notion of binary so the binary will be base64 encoded to a String, and the String added. + */ + public JsonArray add(final byte[] value) { + return null; + } + + /** + * Adds an object to the JSON array. + */ + public JsonArray add(Object value) { + return null; + } + + /** + * Appends all of the elements in the specified array to the end of this JSON array. + */ + public JsonArray addAll(final JsonArray array) { + return null; + } + + // ---------------------------------------------------------------- misc + + /** + * Returns {@code true} if given value exist. + */ + public boolean contains(final Object value) { + return false; + } + + /** + * Removes the specified value from the JSON array. + */ + public boolean remove(final Object value) { + return false; + } + + /** + * Removes the value at the specified position in the JSON array. + */ + public Object remove(final int pos) { + return null; + } + + /** + * Returns the number of values in this JSON array. + */ + public int size() { + return -1; + } + + /** + * Returns {@code true} if JSON array is empty. + */ + public boolean isEmpty() { + return false; + } + + /** + * Returns the underlying list. + */ + public List list() { + return null; + } + + /** + * Removes all entries from the JSON array. + */ + public JsonArray clear() { + return null; + } + + /** + * Returns an iterator over the values in the JSON array. + */ + @Override + public Iterator iterator() { + return null; + } +} diff --git a/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonObject.java b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonObject.java new file mode 100644 index 00000000000..c2a76bb59ff --- /dev/null +++ b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonObject.java @@ -0,0 +1,385 @@ +// Copyright (c) 2003-present, Jodd Team (http://jodd.org) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package jodd.json; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Representation of JSON object. + * @see JsonArray + */ +public class JsonObject implements Iterable> { + + /** + * Create a new, empty instance. + */ + public JsonObject() { + } + + /** + * Create an instance from a Map. The Map is not copied. + */ + public JsonObject(final Map map) { + } + + /** + * Returns the string value with the specified key. + */ + public String getString(final String key) { + return null; + } + + /** + * returns the integer value with the specified key. + */ + public Integer getInteger(final String key) { + return null; + } + + /** + * Returns the long value with the specified key. + */ + public Long getLong(final String key) { + return null; + } + + /** + * Returns the double value with the specified key. + */ + public Double getDouble(final String key) { + return null; + } + + /** + * Returns the float value with the specified key. + */ + public Float getFloat(final String key) { + return null; + } + + /** + * Returns the boolean value with the specified key. + */ + public Boolean getBoolean(final String key) { + return false; + } + + /** + * Returns the {@code JsonObject} value with the specified key. + */ + public JsonObject getJsonObject(final String key) { + return null; + } + + /** + * Returns the {@link JsonArray} value with the specified key + */ + public JsonArray getJsonArray(final String key) { + return null; + } + + /** + * Returns the binary value with the specified key. + *

    + * JSON itself has no notion of a binary. This extension complies to the RFC-7493. + * THe byte array is Base64 encoded binary. + */ + public byte[] getBinary(final String key) { + return null; + } + + /** + * Returns the value with the specified key, as an object. + */ + @SuppressWarnings("unchecked") + public T getValue(final String key) { + return null; + } + + /** + * Like {@link #getString(String)} but specifies a default value to return if there is no entry. + */ + public String getString(final String key, final String def) { + return null; + } + + /** + * Like {@link #getInteger(String)} but specifies a default value to return if there is no entry. + */ + public Integer getInteger(final String key, final Integer def) { + return null; + } + + /** + * Like {@link #getLong(String)} but specifies a default value to return if there is no entry. + */ + public Long getLong(final String key, final Long def) { + return null; + } + + /** + * Like {@link #getDouble(String)} but specifies a default value to return if there is no entry. + */ + public Double getDouble(final String key, final Double def) { + return null; + } + + /** + * Like {@link #getFloat(String)} but specifies a default value to return if there is no entry. + */ + public Float getFloat(final String key, final Float def) { + return null; + } + + /** + * Like {@link #getBoolean(String)} but specifies a default value to return if there is no entry. + */ + public Boolean getBoolean(final String key, final Boolean def) { + return null; + } + + /** + * Like {@link #getJsonObject(String)} but specifies a default value to return if there is no entry. + */ + public JsonObject getJsonObject(final String key, final JsonObject def) { + return null; + } + + /** + * Like {@link #getJsonArray(String)} but specifies a default value to return if there is no entry. + */ + public JsonArray getJsonArray(final String key, final JsonArray def) { + return null; + } + + /** + * Like {@link #getBinary(String)} but specifies a default value to return if there is no entry. + */ + public byte[] getBinary(final String key, final byte[] def) { + return null; + } + + /** + * Like {@link #getValue(String)} but specifies a default value to return if there is no entry. + */ + public T getValue(final String key, final T def) { + return null; + } + + /** + * Returns {@code true} if the JSON object contain the specified key. + */ + public boolean containsKey(final String key) { + return false; + } + + /** + * Return the set of field names in the JSON objects. + */ + public Set fieldNames() { + return null; + } + + // ---------------------------------------------------------------- put + + /** + * Puts an Enum into the JSON object with the specified key. + *

    + * JSON has no concept of encoding Enums, so the Enum will be converted to a String using the {@code java.lang.Enum#name} + * method and the value put as a String. + */ + public JsonObject put(final String key, final Enum value) { + return null; + } + + /** + * Puts an {@code CharSequence} into the JSON object with the specified key. + */ + public JsonObject put(final String key, final CharSequence value) { + return null; + } + + /** + * Puts a string into the JSON object with the specified key. + */ + public JsonObject put(final String key, final String value) { + return null; + } + + /** + * Puts an integer into the JSON object with the specified key. + */ + public JsonObject put(final String key, final Integer value) { + return null; + } + + /** + * Puts a long into the JSON object with the specified key. + */ + public JsonObject put(final String key, final Long value) { + return null; + } + + /** + * Puts a double into the JSON object with the specified key. + */ + public JsonObject put(final String key, final Double value) { + return null; + } + + /** + * Puts a float into the JSON object with the specified key. + */ + public JsonObject put(final String key, final Float value) { + return null; + } + + /** + * Puts a boolean into the JSON object with the specified key. + */ + public JsonObject put(final String key, final Boolean value) { + return null; + } + + /** + * Puts a {@code null} value into the JSON object with the specified key. + */ + public JsonObject putNull(final String key) { + return null; + } + + /** + * Puts another JSON object into the JSON object with the specified key. + */ + public JsonObject put(final String key, final JsonObject value) { + return null; + } + + /** + * Puts a {@link JsonArray} into the JSON object with the specified key. + */ + public JsonObject put(final String key, final JsonArray value) { + return null; + } + + /** + * Puts a {@code byte[]} into the JSON object with the specified key. + *

    + * Follows JSON extension RFC7493, where binary will first be Base64 + * encoded before being put as a String. + */ + public JsonObject put(final String key, final byte[] value) { + return null; + } + + /** + * Puts an object into the JSON object with the specified key. + */ + public JsonObject put(final String key, Object value) { + return null; + } + + @SuppressWarnings("StatementWithEmptyBody") + static Object resolveValue(Object value) { + return null; + } + + + /** + * Removes an entry from this object. + */ + public Object remove(final String key) { + return null; + } + + /** + * Merges in another JSON object. + *

    + * This is the equivalent of putting all the entries of the other JSON object into this object. This is not a deep + * merge, entries containing (sub) JSON objects will be replaced entirely. + */ + public JsonObject mergeIn(final JsonObject other) { + return null; + } + + /** + * Merges in another JSON object. + * A deep merge (recursive) matches (sub) JSON objects in the existing tree and replaces all + * matching entries. JsonArrays are treated like any other entry, i.e. replaced entirely. + */ + public JsonObject mergeInDeep(final JsonObject other) { + return null; + } + + /** + * Merges in another JSON object. + * The merge is deep (recursive) to the specified level. If depth is 0, no merge is performed, + * if depth is greater than the depth of one of the objects, a full deep merge is performed. + */ + @SuppressWarnings("unchecked") + public JsonObject mergeIn(final JsonObject other, final int depth) { + return null; + } + + /** + * Returns the underlying {@code Map} as is. + */ + public Map map() { + return null; + } + + /** + * Returns an iterator of the entries in the JSON object. + */ + @Override + public Iterator> iterator() { + return null; + } + + /** + * Returns the number of entries in the JSON object. + */ + public int size() { + return -1; + } + + /** + * Removes all the entries in this JSON object. + */ + public JsonObject clear() { + return null; + } + + /** + * Returns {@code true} if JSON object is empty. + */ + public boolean isEmpty() { + return false; + } +} diff --git a/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParser.java b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParser.java new file mode 100644 index 00000000000..8055209540c --- /dev/null +++ b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParser.java @@ -0,0 +1,218 @@ +// Copyright (c) 2003-present, Jodd Team (http://jodd.org) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package jodd.json; + +import java.util.List; +import java.util.Map; + +/** + * Simple, developer-friendly JSON parser. It focuses on easy usage + * and type mappings. Uses Jodd's type converters, so it is natural + * companion for Jodd projects. + *

    + * This JSON parser also works in {@link #lazy(boolean)} mode. This + * mode is for top performance usage: parsing is done very, very lazy. + * While you can use all the mappings and other tools, for best performance + * the lazy mode should be used only with maps and lists (no special mappings). + * Also, the performance has it's price: more memory consumption, because the + * original input is hold until the result is in use. + *

    + * See: http://www.ietf.org/rfc/rfc4627.txt + */ +public class JsonParser extends JsonParserBase { + + /** + * Static ctor. + */ + public static JsonParser create() { + return null; + } + + /** + * Creates a lazy implementation of the JSON parser. + */ + public static JsonParser createLazyOne() { + return null; + } + + public JsonParser() { + super(false); + } + + /** + * Enables 'loose' mode for parsing. When 'loose' mode is enabled, + * JSON parsers swallows also invalid JSONs: + *

      + *
    • invalid escape character sequence is simply added to the output
    • + *
    • strings can be quoted with single-quotes
    • + *
    • strings can be unquoted, but may not contain escapes
    • + *
    + */ + public JsonParser looseMode(final boolean looseMode) { + return null; + } + + /** + * Defines if type conversion is strict. If not, all exceptions will be + * caught and replaced with {@code null}. + */ + public JsonParser strictTypes(final boolean strictTypes) { + return null; + } + + /** + * Defines how JSON parser works. In non-lazy mode, the whole JSON is parsed as it is. + * In the lazy mode, not everything is parsed, but some things are left lazy. + * This way we gain performance, especially on partial usage of the whole JSON. + * However, be aware that parser holds the input memory until the returned + * objects are disposed. + */ + public JsonParser lazy(final boolean lazy) { + return null; + } + + /** + * Maps a class to JSONs root. + */ + public JsonParser map(final Class target) { + return null; + } + + /** + * Maps a class to given path. For arrays, append values + * to the path to specify component type (if not specified by + * generics). + */ + public JsonParser map(final String path, final Class target) { + return null; + } + + /** + * Replaces type with mapped type for current path. + */ + protected Class replaceWithMappedTypeForPath(final Class target) { + return null; + } + + /** + * Sets local class meta-data name. + *

    + * Note that by using the class meta-data name you may expose a security hole in case untrusted source + * manages to specify a class that is accessible through class loader and exposes set of methods and/or fields, + * access of which opens an actual security hole. Such classes are known as deserialization gadgets. + * + * Because of this, use of "default typing" is not encouraged in general, and in particular is recommended against + * if the source of content is not trusted. Conversely, default typing may be used for processing content in + * cases where both ends (sender and receiver) are controlled by same entity. + */ + public JsonParser setClassMetadataName(final String name) { + return null; + } + + /** + * Sets usage of default class meta-data name. + * Using it may introduce a security hole, see {@link #setClassMetadataName(String)} for more details. + * @see #setClassMetadataName(String) + */ + public JsonParser withClassMetadata(final boolean useMetadata) { + return null; + } + + /** + * Adds a {@link jodd.util.Wildcard wildcard} pattern for white-listing classes. + * @see #setClassMetadataName(String) + */ + public JsonParser allowClass(final String classPattern) { + return null; + } + + /** + * Removes the whitelist of allowed classes. + * @see #setClassMetadataName(String) + */ + public JsonParser allowAllClasses() { + return null; + } + + /** + * Parses input JSON as given type. + */ + @SuppressWarnings("unchecked") + public T parse(final String input, final Class targetType) { + return null; + } + + /** + * Parses input JSON to {@link JsonObject}, special case of {@link #parse(String, Class)}. + */ + public JsonObject parseAsJsonObject(final String input) { + return null; + } + + /** + * Parses input JSON to {@link JsonArray}, special case of parsing. + */ + public JsonArray parseAsJsonArray(final String input) { + return null; + } + + /** + * Parses input JSON to a list with specified component type. + */ + public List parseAsList(final String string, final Class componentType) { + return null; + } + + /** + * Parses input JSON to a list with specified key and value types. + */ + public Map parseAsMap( + final String string, final Class keyType, final Class valueType) { + return null; + } + + /** + * Parses input JSON string. + */ + public T parse(final String input) { + return null; + } + + /** + * Parses input JSON as given type. + */ + @SuppressWarnings("unchecked") + public T parse(final char[] input, final Class targetType) { + return null; + } + + /** + * Parses input JSON char array. + */ + public T parse(final char[] input) { + return null; + } +} diff --git a/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParserBase.java b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParserBase.java new file mode 100644 index 00000000000..c4ba9194211 --- /dev/null +++ b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/JsonParserBase.java @@ -0,0 +1,68 @@ +// Copyright (c) 2003-present, Jodd Team (http://jodd.org) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package jodd.json; + +import java.util.Collection; + +/** + * Just a base class of {@link jodd.json.JsonParser} that contains + * various utilities, to reduce the size of a parser. + */ +public abstract class JsonParserBase { + public JsonParserBase(final boolean strictTypes) { + } + + /** + * Creates new instance of {@link jodd.json.MapToBean}. + */ + protected MapToBean createMapToBean(final String classMetadataName) { + return null; + } + + /** + * Creates new type for JSON array objects. + * It returns a collection. + * Later, the collection will be converted into the target type. + */ + @SuppressWarnings("unchecked") + protected Collection newArrayInstance(final Class targetType) { + return null; + } + + /** + * Creates new object or a HashMap if type is not specified. + */ + protected Object newObjectInstance(final Class targetType) { + return null; + } + + /** + * Converts type of the given value. + */ + protected Object convertType(final Object value, final Class targetType) { + return null; + } +} diff --git a/java/ql/test/stubs/joddjson-6.0.3/jodd/json/MapToBean.java b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/MapToBean.java new file mode 100644 index 00000000000..f48b69d0fe8 --- /dev/null +++ b/java/ql/test/stubs/joddjson-6.0.3/jodd/json/MapToBean.java @@ -0,0 +1,45 @@ +// Copyright (c) 2003-present, Jodd Team (http://jodd.org) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +package jodd.json; + +import java.util.Map; + +/** + * Map to bean converter. + * Used when parsing with class metadata enabled. + */ +public class MapToBean { + + public MapToBean(final JsonParserBase jsonParser, final String classMetadataName) { + } + + /** + * Converts map to target type. + */ + public Object map2bean(final Map map, Class targetType) { + return null; + } +} From e11707776150b8b988b987a9f19a95a5783d39ac Mon Sep 17 00:00:00 2001 From: "Raul Garcia (MSFT)" Date: Thu, 5 Aug 2021 15:29:18 -0700 Subject: [PATCH 150/429] Adding change-note --- csharp/change-notes/2021-08-05-insecure-randomness.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 csharp/change-notes/2021-08-05-insecure-randomness.md diff --git a/csharp/change-notes/2021-08-05-insecure-randomness.md b/csharp/change-notes/2021-08-05-insecure-randomness.md new file mode 100644 index 00000000000..29b5e5d4884 --- /dev/null +++ b/csharp/change-notes/2021-08-05-insecure-randomness.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Adding `Membership.GeneratePassword()` as a bad source of random data. \ No newline at end of file From 2708326624164520251816b204627811cf0019ef Mon Sep 17 00:00:00 2001 From: Raul Garcia <42392023+raulgarciamsft@users.noreply.github.com> Date: Thu, 5 Aug 2021 16:33:01 -0700 Subject: [PATCH 151/429] Update csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> --- .../query-tests/Security Features/CWE-338/InsecureRandomness.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs index 3503bff8f41..58241499c66 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-338/InsecureRandomness.cs @@ -76,7 +76,7 @@ public class InsecureRandomness public static string BiasPasswordGeneration() { - // BAD: Membership.GeneratePassword is generates a password with a bias + // BAD: Membership.GeneratePassword generates a password with a bias string password = System.Web.Security.Membership.GeneratePassword(12, 3); return password; } From 51a7018afc0cba8ac7201c4edaf31fbd70976b64 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 27 Jul 2021 10:05:22 +0100 Subject: [PATCH 152/429] Add stubs --- .../commons/collections4/ArrayStack.java | 17 +++ .../org/apache/commons/collections4/Bag.java | 22 +++ .../apache/commons/collections4/BagUtils.java | 26 ++++ .../apache/commons/collections4/BidiMap.java | 15 ++ .../apache/commons/collections4/Closure.java | 9 ++ .../commons/collections4/CollectionUtils.java | 87 +++++++++++ .../collections4/EnumerationUtils.java | 15 ++ .../apache/commons/collections4/Equator.java | 10 ++ .../commons/collections4/FluentIterable.java | 49 ++++++ .../commons/collections4/IterableUtils.java | 60 ++++++++ .../commons/collections4/IteratorUtils.java | 103 +++++++++++++ .../commons/collections4/ListUtils.java | 39 +++++ .../commons/collections4/ListValuedMap.java | 12 ++ .../apache/commons/collections4/MapUtils.java | 140 +++++++++--------- .../commons/collections4/MultiMapUtils.java | 29 ++++ .../apache/commons/collections4/MultiSet.java | 33 +++++ .../commons/collections4/MultiSetUtils.java | 16 ++ .../commons/collections4/MultiValuedMap.java | 32 ++++ .../commons/collections4/OrderedBidiMap.java | 11 ++ .../commons/collections4/QueueUtils.java | 18 +++ .../collections4/ResettableIterator.java | 10 ++ .../collections4/ResettableListIterator.java | 11 ++ .../apache/commons/collections4/SetUtils.java | 52 +++++++ .../commons/collections4/SetValuedMap.java | 12 ++ .../commons/collections4/SortedBag.java | 13 ++ .../commons/collections4/SplitMapUtils.java | 15 ++ .../org/apache/commons/collections4/Trie.java | 11 ++ .../commons/collections4/TrieUtils.java | 11 ++ .../collections4/bag/AbstractMapBag.java | 50 +++++++ .../commons/collections4/bag/TreeBag.java | 22 +++ .../collections4/bidimap/TreeBidiMap.java | 38 +++++ .../iterators/AbstractIteratorDecorator.java | 13 ++ .../AbstractUntypedIteratorDecorator.java | 14 ++ .../iterators/BoundedIterator.java | 14 ++ .../iterators/IteratorEnumeration.java | 16 ++ .../iterators/NodeListIterator.java | 17 +++ .../iterators/SkippingIterator.java | 14 ++ .../iterators/ZippingIterator.java | 16 ++ .../keyvalue/DefaultMapEntry.java | 2 - .../keyvalue/UnmodifiableMapEntry.java | 2 - .../collections4/map/AbstractHashedMap.java | 133 +++++++++++++++++ .../collections4/map/AbstractLinkedMap.java | 44 ++++++ .../commons/collections4/map/HashedMap.java | 16 ++ .../commons/collections4/map/LinkedMap.java | 22 +++ .../collections4/map/MultiValueMap.java | 14 +- .../multimap/AbstractListValuedMap.java | 19 +++ .../multimap/AbstractMultiValuedMap.java | 46 ++++++ .../multimap/AbstractSetValuedMap.java | 19 +++ .../multimap/ArrayListValuedHashMap.java | 20 +++ .../multimap/HashSetValuedHashMap.java | 19 +++ .../multiset/AbstractMapMultiSet.java | 43 ++++++ .../multiset/AbstractMultiSet.java | 39 +++++ .../collections4/multiset/HashMultiSet.java | 13 ++ .../trie/AbstractBitwiseTrie.java | 39 +++++ .../trie/AbstractPatriciaTrie.java | 76 ++++++++++ .../collections4/trie/KeyAnalyzer.java | 24 +++ .../collections4/trie/PatriciaTrie.java | 12 ++ .../org/w3c/dom/Attr.java | 18 +++ .../org/w3c/dom/CDATASection.java | 9 ++ .../org/w3c/dom/CharacterData.java | 17 +++ .../org/w3c/dom/Comment.java | 9 ++ .../org/w3c/dom/DOMConfiguration.java | 13 ++ .../org/w3c/dom/DOMImplementation.java | 14 ++ .../org/w3c/dom/DOMStringList.java | 11 ++ .../org/w3c/dom/Document.java | 52 +++++++ .../org/w3c/dom/DocumentFragment.java | 9 ++ .../org/w3c/dom/DocumentType.java | 16 ++ .../org/w3c/dom/Element.java | 32 ++++ .../org/w3c/dom/EntityReference.java | 9 ++ .../org/w3c/dom/NamedNodeMap.java | 17 +++ .../org/w3c/dom/Node.java | 67 +++++++++ .../org/w3c/dom/NodeList.java | 11 ++ .../org/w3c/dom/ProcessingInstruction.java | 12 ++ .../org/w3c/dom/Text.java | 13 ++ .../org/w3c/dom/TypeInfo.java | 15 ++ .../org/w3c/dom/UserDataHandler.java | 15 ++ 76 files changed, 1970 insertions(+), 83 deletions(-) create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ArrayStack.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Bag.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BagUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BidiMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Closure.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/CollectionUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/EnumerationUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Equator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/FluentIterable.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IterableUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IteratorUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiMapUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSet.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSetUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/OrderedBidiMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/QueueUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableListIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SortedBag.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SplitMapUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Trie.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/TrieUtils.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/AbstractMapBag.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/TreeBag.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bidimap/TreeBidiMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractIteratorDecorator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractUntypedIteratorDecorator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/BoundedIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/IteratorEnumeration.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/NodeListIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/SkippingIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/ZippingIterator.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractHashedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractLinkedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/HashedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/LinkedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractListValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMapMultiSet.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMultiSet.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/HashMultiSet.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractBitwiseTrie.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractPatriciaTrie.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/KeyAnalyzer.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/PatriciaTrie.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Attr.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CDATASection.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CharacterData.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Comment.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMConfiguration.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMImplementation.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMStringList.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Document.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentFragment.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentType.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Element.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/EntityReference.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NamedNodeMap.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Node.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NodeList.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/ProcessingInstruction.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Text.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/TypeInfo.java create mode 100644 java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/UserDataHandler.java diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ArrayStack.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ArrayStack.java new file mode 100644 index 00000000000..19c2e065588 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ArrayStack.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.commons.collections4.ArrayStack for testing purposes + +package org.apache.commons.collections4; + +import java.util.ArrayList; + +public class ArrayStack extends ArrayList +{ + public ArrayStack(){} + public ArrayStack(int p0){} + public E peek(){ return null; } + public E peek(int p0){ return null; } + public E pop(){ return null; } + public E push(E p0){ return null; } + public boolean empty(){ return false; } + public int search(Object p0){ return 0; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Bag.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Bag.java new file mode 100644 index 00000000000..da4f3970959 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Bag.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.commons.collections4.Bag for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public interface Bag extends Collection +{ + Iterator iterator(); + Set uniqueSet(); + boolean add(E p0); + boolean add(E p0, int p1); + boolean containsAll(Collection p0); + boolean remove(Object p0); + boolean remove(Object p0, int p1); + boolean removeAll(Collection p0); + boolean retainAll(Collection p0); + int getCount(Object p0); + int size(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BagUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BagUtils.java new file mode 100644 index 00000000000..054fe450c6e --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BagUtils.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.commons.collections4.BagUtils for testing purposes + +package org.apache.commons.collections4; + +import org.apache.commons.collections4.Bag; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.SortedBag; +import org.apache.commons.collections4.Transformer; + +public class BagUtils +{ + protected BagUtils() {} + public static Bag collectionBag(Bag p0){ return null; } + public static Bag emptyBag(){ return null; } + public static Bag predicatedBag(Bag p0, Predicate p1){ return null; } + public static Bag synchronizedBag(Bag p0){ return null; } + public static Bag transformingBag(Bag p0, Transformer p1){ return null; } + public static Bag unmodifiableBag(Bag p0){ return null; } + public static SortedBag emptySortedBag(){ return null; } + public static SortedBag predicatedSortedBag(SortedBag p0, Predicate p1){ return null; } + public static SortedBag synchronizedSortedBag(SortedBag p0){ return null; } + public static SortedBag transformingSortedBag(SortedBag p0, Transformer p1){ return null; } + public static SortedBag unmodifiableSortedBag(SortedBag p0){ return null; } + public static Bag EMPTY_BAG = null; + public static Bag EMPTY_SORTED_BAG = null; +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BidiMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BidiMap.java new file mode 100644 index 00000000000..95e4e806ac4 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/BidiMap.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.commons.collections4.BidiMap for testing purposes + +package org.apache.commons.collections4; + +import java.util.Set; +import org.apache.commons.collections4.IterableMap; + +public interface BidiMap extends IterableMap +{ + BidiMap inverseBidiMap(); + K getKey(Object p0); + K removeValue(Object p0); + Set values(); + V put(K p0, V p1); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Closure.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Closure.java new file mode 100644 index 00000000000..d84efcf2870 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Closure.java @@ -0,0 +1,9 @@ +// Generated automatically from org.apache.commons.collections4.Closure for testing purposes + +package org.apache.commons.collections4; + + +public interface Closure +{ + void execute(T p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/CollectionUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/CollectionUtils.java new file mode 100644 index 00000000000..c3d799375a9 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/CollectionUtils.java @@ -0,0 +1,87 @@ +// Generated automatically from org.apache.commons.collections4.CollectionUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.Closure; +import org.apache.commons.collections4.Equator; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class CollectionUtils +{ + protected CollectionUtils() {} + public static Collection predicatedCollection(Collection p0, Predicate p1){ return null; } + public static Collection retainAll(Collection p0, Collection p1){ return null; } + public static Collection synchronizedCollection(Collection p0){ return null; } + public static Collection unmodifiableCollection(Collection p0){ return null; } + public static boolean addAll(Collection p0, C... p1){ return false; } + public static boolean addAll(Collection p0, Enumeration p1){ return false; } + public static boolean addAll(Collection p0, Iterable p1){ return false; } + public static boolean addAll(Collection p0, Iterator p1){ return false; } + public static boolean exists(Iterable p0, Predicate p1){ return false; } + public static boolean matchesAll(Iterable p0, Predicate p1){ return false; } + public static int countMatches(Iterable p0, Predicate p1){ return 0; } + public static void transform(Collection p0, Transformer p1){} + public static Collection removeAll(Collection p0, Collection p1){ return null; } + public static Collection removeAll(Iterable p0, Iterable p1, Equator p2){ return null; } + public static Collection retainAll(Iterable p0, Iterable p1, Equator p2){ return null; } + public static Collection transformingCollection(Collection p0, Transformer p1){ return null; } + public static Collection> permutations(Collection p0){ return null; } + public static E extractSingleton(Collection p0){ return null; } + public static boolean isEqualCollection(Collection p0, Collection p1, Equator p2){ return false; } + public static > R collect(Iterable p0, Transformer p1, R p2){ return null; } + public static > R collect(Iterator p0, Transformer p1, R p2){ return null; } + public static Collection collect(Iterable p0, Transformer p1){ return null; } + public static Collection collect(Iterator p0, Transformer p1){ return null; } + public static Map.Entry get(Map p0, int p1){ return null; } + public static > List collate(Iterable p0, Iterable p1){ return null; } + public static > List collate(Iterable p0, Iterable p1, boolean p2){ return null; } + public static > R select(Iterable p0, Predicate p1, R p2){ return null; } + public static > R select(Iterable p0, Predicate p1, R p2, R p3){ return null; } + public static > R selectRejected(Iterable p0, Predicate p1, R p2){ return null; } + public static Collection disjunction(Iterable p0, Iterable p1){ return null; } + public static Collection intersection(Iterable p0, Iterable p1){ return null; } + public static Collection select(Iterable p0, Predicate p1){ return null; } + public static Collection selectRejected(Iterable p0, Predicate p1){ return null; } + public static Collection subtract(Iterable p0, Iterable p1){ return null; } + public static Collection subtract(Iterable p0, Iterable p1, Predicate p2){ return null; } + public static Collection union(Iterable p0, Iterable p1){ return null; } + public static List collate(Iterable p0, Iterable p1, Comparator p2){ return null; } + public static List collate(Iterable p0, Iterable p1, Comparator p2, boolean p3){ return null; } + public static Map getCardinalityMap(Iterable p0){ return null; } + public static int cardinality(O p0, Iterable p1){ return 0; } + public static > C forAllDo(Iterable p0, C p1){ return null; } + public static > C forAllDo(Iterator p0, C p1){ return null; } + public static > T forAllButLastDo(Iterable p0, C p1){ return null; } + public static > T forAllButLastDo(Iterator p0, C p1){ return null; } + public static Collection emptyCollection(){ return null; } + public static Collection emptyIfNull(Collection p0){ return null; } + public static T find(Iterable p0, Predicate p1){ return null; } + public static T get(Iterable p0, int p1){ return null; } + public static T get(Iterator p0, int p1){ return null; } + public static boolean addIgnoreNull(Collection p0, T p1){ return false; } + public static boolean containsAny(Collection p0, T... p1){ return false; } + public static boolean filter(Iterable p0, Predicate p1){ return false; } + public static boolean filterInverse(Iterable p0, Predicate p1){ return false; } + public static Collection EMPTY_COLLECTION = null; + public static Object get(Object p0, int p1){ return null; } + public static boolean containsAll(Collection p0, Collection p1){ return false; } + public static boolean containsAny(Collection p0, Collection p1){ return false; } + public static boolean isEmpty(Collection p0){ return false; } + public static boolean isEqualCollection(Collection p0, Collection p1){ return false; } + public static boolean isFull(Collection p0){ return false; } + public static boolean isNotEmpty(Collection p0){ return false; } + public static boolean isProperSubCollection(Collection p0, Collection p1){ return false; } + public static boolean isSubCollection(Collection p0, Collection p1){ return false; } + public static boolean sizeIsEmpty(Object p0){ return false; } + public static int maxSize(Collection p0){ return 0; } + public static int size(Object p0){ return 0; } + public static void reverseArray(Object[] p0){} + static void checkIndexBounds(int p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/EnumerationUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/EnumerationUtils.java new file mode 100644 index 00000000000..5aa0ef01826 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/EnumerationUtils.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.commons.collections4.EnumerationUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Enumeration; +import java.util.List; +import java.util.StringTokenizer; + +public class EnumerationUtils +{ + protected EnumerationUtils() {} + public static List toList(Enumeration p0){ return null; } + public static T get(Enumeration p0, int p1){ return null; } + public static List toList(StringTokenizer p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Equator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Equator.java new file mode 100644 index 00000000000..fed02e03367 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Equator.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.commons.collections4.Equator for testing purposes + +package org.apache.commons.collections4; + + +public interface Equator +{ + boolean equate(T p0, T p1); + int hash(T p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/FluentIterable.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/FluentIterable.java new file mode 100644 index 00000000000..4eeed765238 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/FluentIterable.java @@ -0,0 +1,49 @@ +// Generated automatically from org.apache.commons.collections4.FluentIterable for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import org.apache.commons.collections4.Closure; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class FluentIterable implements Iterable +{ + FluentIterable(){} + public FluentIterable transform(Transformer p0){ return null; } + public E get(int p0){ return null; } + public E[] toArray(Class p0){ return null; } + public Enumeration asEnumeration(){ return null; } + public FluentIterable append(E... p0){ return null; } + public FluentIterable append(Iterable p0){ return null; } + public FluentIterable collate(Iterable p0){ return null; } + public FluentIterable collate(Iterable p0, Comparator p1){ return null; } + public FluentIterable eval(){ return null; } + public FluentIterable filter(Predicate p0){ return null; } + public FluentIterable limit(long p0){ return null; } + public FluentIterable loop(){ return null; } + public FluentIterable reverse(){ return null; } + public FluentIterable skip(long p0){ return null; } + public FluentIterable unique(){ return null; } + public FluentIterable unmodifiable(){ return null; } + public FluentIterable zip(Iterable p0){ return null; } + public FluentIterable zip(Iterable... p0){ return null; } + public Iterator iterator(){ return null; } + public List toList(){ return null; } + public String toString(){ return null; } + public boolean allMatch(Predicate p0){ return false; } + public boolean anyMatch(Predicate p0){ return false; } + public boolean contains(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int size(){ return 0; } + public static FluentIterable empty(){ return null; } + public static FluentIterable of(Iterable p0){ return null; } + public static FluentIterable of(T p0){ return null; } + public static FluentIterable of(T... p0){ return null; } + public void copyInto(Collection p0){} + public void forEach(Closure p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IterableUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IterableUtils.java new file mode 100644 index 00000000000..5df2cb09966 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IterableUtils.java @@ -0,0 +1,60 @@ +// Generated automatically from org.apache.commons.collections4.IterableUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import org.apache.commons.collections4.Closure; +import org.apache.commons.collections4.Equator; +import org.apache.commons.collections4.Factory; +import org.apache.commons.collections4.FluentIterable; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class IterableUtils +{ + public IterableUtils(){} + public static int frequency(Iterable p0, T p1){ return 0; } + public static E find(Iterable p0, Predicate p1){ return null; } + public static E forEachButLast(Iterable p0, Closure p1){ return null; } + public static Iterable boundedIterable(Iterable p0, long p1){ return null; } + public static Iterable chainedIterable(Iterable p0, Iterable p1){ return null; } + public static Iterable chainedIterable(Iterable p0, Iterable p1, Iterable p2){ return null; } + public static Iterable chainedIterable(Iterable p0, Iterable p1, Iterable p2, Iterable p3){ return null; } + public static Iterable chainedIterable(Iterable... p0){ return null; } + public static Iterable collatedIterable(Comparator p0, Iterable p1, Iterable p2){ return null; } + public static Iterable collatedIterable(Iterable p0, Iterable p1){ return null; } + public static Iterable emptyIfNull(Iterable p0){ return null; } + public static Iterable emptyIterable(){ return null; } + public static Iterable filteredIterable(Iterable p0, Predicate p1){ return null; } + public static Iterable loopingIterable(Iterable p0){ return null; } + public static Iterable reversedIterable(Iterable p0){ return null; } + public static Iterable skippingIterable(Iterable p0, long p1){ return null; } + public static Iterable uniqueIterable(Iterable p0){ return null; } + public static Iterable unmodifiableIterable(Iterable p0){ return null; } + public static Iterable zippingIterable(Iterable p0, Iterable p1){ return null; } + public static Iterable zippingIterable(Iterable p0, Iterable... p1){ return null; } + public static List toList(Iterable p0){ return null; } + public static String toString(Iterable p0){ return null; } + public static String toString(Iterable p0, Transformer p1){ return null; } + public static String toString(Iterable p0, Transformer p1, String p2, String p3, String p4){ return null; } + public static boolean contains(Iterable p0, E p1, Equator p2){ return false; } + public static boolean contains(Iterable p0, Object p1){ return false; } + public static boolean matchesAll(Iterable p0, Predicate p1){ return false; } + public static boolean matchesAny(Iterable p0, Predicate p1){ return false; } + public static int indexOf(Iterable p0, Predicate p1){ return 0; } + public static long countMatches(Iterable p0, Predicate p1){ return 0; } + public static void forEach(Iterable p0, Closure p1){} + public static Iterable transformedIterable(Iterable p0, Transformer p1){ return null; } + public static > List partition(Iterable p0, Factory p1, Predicate... p2){ return null; } + public static List> partition(Iterable p0, Predicate p1){ return null; } + public static List> partition(Iterable p0, Predicate... p1){ return null; } + public static T first(Iterable p0){ return null; } + public static T get(Iterable p0, int p1){ return null; } + public static boolean isEmpty(Iterable p0){ return false; } + public static int size(Iterable p0){ return 0; } + static FluentIterable EMPTY_ITERABLE = null; + static void checkNotNull(Iterable p0){} + static void checkNotNull(Iterable... p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IteratorUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IteratorUtils.java new file mode 100644 index 00000000000..35798256866 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/IteratorUtils.java @@ -0,0 +1,103 @@ +// Generated automatically from org.apache.commons.collections4.IteratorUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.apache.commons.collections4.Closure; +import org.apache.commons.collections4.MapIterator; +import org.apache.commons.collections4.OrderedIterator; +import org.apache.commons.collections4.OrderedMapIterator; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.ResettableIterator; +import org.apache.commons.collections4.ResettableListIterator; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.collections4.iterators.BoundedIterator; +import org.apache.commons.collections4.iterators.NodeListIterator; +import org.apache.commons.collections4.iterators.SkippingIterator; +import org.apache.commons.collections4.iterators.ZippingIterator; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class IteratorUtils +{ + protected IteratorUtils() {} + public static BoundedIterator boundedIterator(Iterator p0, long p1){ return null; } + public static BoundedIterator boundedIterator(Iterator p0, long p1, long p2){ return null; } + public static E find(Iterator p0, Predicate p1){ return null; } + public static E first(Iterator p0){ return null; } + public static E forEachButLast(Iterator p0, Closure p1){ return null; } + public static E get(Iterator p0, int p1){ return null; } + public static E[] toArray(Iterator p0, Class p1){ return null; } + public static Enumeration asEnumeration(Iterator p0){ return null; } + public static Iterable asIterable(Iterator p0){ return null; } + public static Iterable asMultipleUseIterable(Iterator p0){ return null; } + public static Iterator asIterator(Enumeration p0){ return null; } + public static Iterator asIterator(Enumeration p0, Collection p1){ return null; } + public static Iterator chainedIterator(Collection> p0){ return null; } + public static Iterator chainedIterator(Iterator p0, Iterator p1){ return null; } + public static Iterator chainedIterator(Iterator... p0){ return null; } + public static Iterator collatedIterator(Comparator p0, Collection> p1){ return null; } + public static Iterator collatedIterator(Comparator p0, Iterator p1, Iterator p2){ return null; } + public static Iterator collatedIterator(Comparator p0, Iterator... p1){ return null; } + public static Iterator filteredIterator(Iterator p0, Predicate p1){ return null; } + public static Iterator objectGraphIterator(E p0, Transformer p1){ return null; } + public static Iterator peekingIterator(Iterator p0){ return null; } + public static Iterator pushbackIterator(Iterator p0){ return null; } + public static Iterator unmodifiableIterator(Iterator p0){ return null; } + public static List toList(Iterator p0){ return null; } + public static List toList(Iterator p0, int p1){ return null; } + public static ListIterator filteredListIterator(ListIterator p0, Predicate p1){ return null; } + public static ListIterator singletonListIterator(E p0){ return null; } + public static ListIterator toListIterator(Iterator p0){ return null; } + public static ListIterator unmodifiableListIterator(ListIterator p0){ return null; } + public static OrderedIterator emptyOrderedIterator(){ return null; } + public static ResettableIterator arrayIterator(E... p0){ return null; } + public static ResettableIterator arrayIterator(E[] p0, int p1){ return null; } + public static ResettableIterator arrayIterator(E[] p0, int p1, int p2){ return null; } + public static ResettableIterator arrayIterator(Object p0){ return null; } + public static ResettableIterator arrayIterator(Object p0, int p1){ return null; } + public static ResettableIterator arrayIterator(Object p0, int p1, int p2){ return null; } + public static ResettableIterator emptyIterator(){ return null; } + public static ResettableIterator loopingIterator(Collection p0){ return null; } + public static ResettableIterator singletonIterator(E p0){ return null; } + public static ResettableListIterator arrayListIterator(E... p0){ return null; } + public static ResettableListIterator arrayListIterator(E[] p0, int p1){ return null; } + public static ResettableListIterator arrayListIterator(E[] p0, int p1, int p2){ return null; } + public static ResettableListIterator arrayListIterator(Object p0){ return null; } + public static ResettableListIterator arrayListIterator(Object p0, int p1){ return null; } + public static ResettableListIterator arrayListIterator(Object p0, int p1, int p2){ return null; } + public static ResettableListIterator emptyListIterator(){ return null; } + public static ResettableListIterator loopingListIterator(List p0){ return null; } + public static SkippingIterator skippingIterator(Iterator p0, long p1){ return null; } + public static String toString(Iterator p0){ return null; } + public static String toString(Iterator p0, Transformer p1){ return null; } + public static String toString(Iterator p0, Transformer p1, String p2, String p3, String p4){ return null; } + public static ZippingIterator zippingIterator(Iterator p0, Iterator p1){ return null; } + public static ZippingIterator zippingIterator(Iterator p0, Iterator p1, Iterator p2){ return null; } + public static ZippingIterator zippingIterator(Iterator... p0){ return null; } + public static boolean contains(Iterator p0, Object p1){ return false; } + public static boolean matchesAll(Iterator p0, Predicate p1){ return false; } + public static boolean matchesAny(Iterator p0, Predicate p1){ return false; } + public static int indexOf(Iterator p0, Predicate p1){ return 0; } + public static void forEach(Iterator p0, Closure p1){} + public static Iterator transformedIterator(Iterator p0, Transformer p1){ return null; } + public static MapIterator emptyMapIterator(){ return null; } + public static MapIterator unmodifiableMapIterator(MapIterator p0){ return null; } + public static OrderedMapIterator emptyOrderedMapIterator(){ return null; } + public static Iterator getIterator(Object p0){ return null; } + public static MapIterator EMPTY_MAP_ITERATOR = null; + public static NodeListIterator nodeListIterator(Node p0){ return null; } + public static NodeListIterator nodeListIterator(NodeList p0){ return null; } + public static Object[] toArray(Iterator p0){ return null; } + public static OrderedIterator EMPTY_ORDERED_ITERATOR = null; + public static OrderedMapIterator EMPTY_ORDERED_MAP_ITERATOR = null; + public static ResettableIterator EMPTY_ITERATOR = null; + public static ResettableListIterator EMPTY_LIST_ITERATOR = null; + public static boolean isEmpty(Iterator p0){ return false; } + public static int size(Iterator p0){ return 0; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListUtils.java new file mode 100644 index 00000000000..66aa4a6567f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListUtils.java @@ -0,0 +1,39 @@ +// Generated automatically from org.apache.commons.collections4.ListUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.List; +import org.apache.commons.collections4.Equator; +import org.apache.commons.collections4.Factory; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class ListUtils +{ + protected ListUtils() {} + public static List fixedSizeList(List p0){ return null; } + public static List intersection(List p0, List p1){ return null; } + public static List lazyList(List p0, Factory p1){ return null; } + public static List lazyList(List p0, Transformer p1){ return null; } + public static List longestCommonSubsequence(List p0, List p1){ return null; } + public static List longestCommonSubsequence(List p0, List p1, Equator p2){ return null; } + public static List predicatedList(List p0, Predicate p1){ return null; } + public static List removeAll(Collection p0, Collection p1){ return null; } + public static List retainAll(Collection p0, Collection p1){ return null; } + public static List select(Collection p0, Predicate p1){ return null; } + public static List selectRejected(Collection p0, Predicate p1){ return null; } + public static List subtract(List p0, List p1){ return null; } + public static List sum(List p0, List p1){ return null; } + public static List synchronizedList(List p0){ return null; } + public static List transformedList(List p0, Transformer p1){ return null; } + public static List union(List p0, List p1){ return null; } + public static List unmodifiableList(List p0){ return null; } + public static int indexOf(List p0, Predicate p1){ return 0; } + public static List> partition(List p0, int p1){ return null; } + public static List defaultIfNull(List p0, List p1){ return null; } + public static List emptyIfNull(List p0){ return null; } + public static String longestCommonSubsequence(CharSequence p0, CharSequence p1){ return null; } + public static boolean isEqualList(Collection p0, Collection p1){ return false; } + public static int hashCodeForList(Collection p0){ return 0; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListValuedMap.java new file mode 100644 index 00000000000..55db7cd09e1 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ListValuedMap.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.collections4.ListValuedMap for testing purposes + +package org.apache.commons.collections4; + +import java.util.List; +import org.apache.commons.collections4.MultiValuedMap; + +public interface ListValuedMap extends MultiValuedMap +{ + List get(K p0); + List remove(Object p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MapUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MapUtils.java index 1ec008c0caa..7d31108b681 100644 --- a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MapUtils.java +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MapUtils.java @@ -20,76 +20,76 @@ import org.apache.commons.collections4.map.MultiValueMap; public class MapUtils { protected MapUtils() {} - public static MultiValueMap multiValueMap(Map p0, Class p1){ return null; } - public static MultiValueMap multiValueMap(Map p0, Factory p1){ return null; } - public static void populateMap(Map p0, Iterable p1, Transformer p2, Transformer p3){} - public static void populateMap(MultiMap p0, Iterable p1, Transformer p2, Transformer p3){} - public static IterableMap fixedSizeMap(Map p0){ return null; } - public static IterableMap iterableMap(Map p0){ return null; } - public static IterableMap lazyMap(Map p0, Factory p1){ return null; } - public static IterableMap lazyMap(Map p0, Transformer p1){ return null; } - public static IterableMap predicatedMap(Map p0, Predicate p1, Predicate p2){ return null; } - public static IterableMap transformedMap(Map p0, Transformer p1, Transformer p2){ return null; } - public static IterableSortedMap iterableSortedMap(SortedMap p0){ return null; } - public static Map emptyIfNull(Map p0){ return null; } - public static Map putAll(Map p0, Object[] p1){ return null; } - public static Map synchronizedMap(Map p0){ return null; } - public static Map unmodifiableMap(Map p0){ return null; } - public static Map invertMap(Map p0){ return null; } - public static MultiValueMap multiValueMap(Map> p0){ return null; } - public static OrderedMap orderedMap(Map p0){ return null; } - public static Properties toProperties(Map p0){ return null; } - public static SortedMap fixedSizeSortedMap(SortedMap p0){ return null; } - public static SortedMap lazySortedMap(SortedMap p0, Factory p1){ return null; } - public static SortedMap lazySortedMap(SortedMap p0, Transformer p1){ return null; } - public static SortedMap predicatedSortedMap(SortedMap p0, Predicate p1, Predicate p2){ return null; } - public static SortedMap synchronizedSortedMap(SortedMap p0){ return null; } - public static SortedMap transformedSortedMap(SortedMap p0, Transformer p1, Transformer p2){ return null; } - public static SortedMap unmodifiableSortedMap(SortedMap p0){ return null; } - public static V getObject(Map p0, K p1){ return null; } - public static V getObject(Map p0, K p1, V p2){ return null; } - public static void populateMap(Map p0, Iterable p1, Transformer p2){} - public static void populateMap(MultiMap p0, Iterable p1, Transformer p2){} - public static Boolean getBoolean(Map p0, K p1){ return null; } - public static Boolean getBoolean(Map p0, K p1, Boolean p2){ return null; } - public static Byte getByte(Map p0, K p1){ return null; } - public static Byte getByte(Map p0, K p1, Byte p2){ return null; } - public static Double getDouble(Map p0, K p1){ return null; } - public static Double getDouble(Map p0, K p1, Double p2){ return null; } - public static Float getFloat(Map p0, K p1){ return null; } - public static Float getFloat(Map p0, K p1, Float p2){ return null; } - public static Integer getInteger(Map p0, K p1){ return null; } - public static Integer getInteger(Map p0, K p1, Integer p2){ return null; } - public static Long getLong(Map p0, K p1){ return null; } - public static Long getLong(Map p0, K p1, Long p2){ return null; } - public static Map getMap(Map p0, K p1){ return null; } - public static Map getMap(Map p0, K p1, Map p2){ return null; } - public static Number getNumber(Map p0, K p1){ return null; } - public static Number getNumber(Map p0, K p1, Number p2){ return null; } - public static Short getShort(Map p0, K p1){ return null; } - public static Short getShort(Map p0, K p1, Short p2){ return null; } - public static String getString(Map p0, K p1){ return null; } - public static String getString(Map p0, K p1, String p2){ return null; } - public static boolean getBooleanValue(Map p0, K p1){ return false; } - public static boolean getBooleanValue(Map p0, K p1, boolean p2){ return false; } - public static byte getByteValue(Map p0, K p1){ return 0; } - public static byte getByteValue(Map p0, K p1, byte p2){ return 0; } - public static double getDoubleValue(Map p0, K p1){ return 0; } - public static double getDoubleValue(Map p0, K p1, double p2){ return 0; } - public static float getFloatValue(Map p0, K p1){ return 0; } - public static float getFloatValue(Map p0, K p1, float p2){ return 0; } - public static int getIntValue(Map p0, K p1){ return 0; } - public static int getIntValue(Map p0, K p1, int p2){ return 0; } - public static long getLongValue(Map p0, K p1){ return 0; } - public static long getLongValue(Map p0, K p1, long p2){ return 0; } - public static short getShortValue(Map p0, K p1){ return 0; } - public static short getShortValue(Map p0, K p1, short p2){ return 0; } - public static void safeAddToMap(Map p0, K p1, Object p2){} + public static > MultiValueMap multiValueMap(Map p0, Class p1){ return null; } + public static > MultiValueMap multiValueMap(Map p0, Factory p1){ return null; } + public static void populateMap(Map p0, Iterable p1, Transformer p2, Transformer p3){} + public static void populateMap(MultiMap p0, Iterable p1, Transformer p2, Transformer p3){} + public static IterableMap fixedSizeMap(Map p0){ return null; } + public static IterableMap iterableMap(Map p0){ return null; } + public static IterableMap lazyMap(Map p0, Factory p1){ return null; } + public static IterableMap lazyMap(Map p0, Transformer p1){ return null; } + public static IterableMap predicatedMap(Map p0, Predicate p1, Predicate p2){ return null; } + public static IterableMap transformedMap(Map p0, Transformer p1, Transformer p2){ return null; } + public static IterableSortedMap iterableSortedMap(SortedMap p0){ return null; } + public static Map emptyIfNull(Map p0){ return null; } + public static Map putAll(Map p0, Object[] p1){ return null; } + public static Map synchronizedMap(Map p0){ return null; } + public static Map unmodifiableMap(Map p0){ return null; } + public static Map invertMap(Map p0){ return null; } + public static MultiValueMap multiValueMap(Map> p0){ return null; } + public static OrderedMap orderedMap(Map p0){ return null; } + public static Properties toProperties(Map p0){ return null; } + public static SortedMap fixedSizeSortedMap(SortedMap p0){ return null; } + public static SortedMap lazySortedMap(SortedMap p0, Factory p1){ return null; } + public static SortedMap lazySortedMap(SortedMap p0, Transformer p1){ return null; } + public static SortedMap predicatedSortedMap(SortedMap p0, Predicate p1, Predicate p2){ return null; } + public static SortedMap synchronizedSortedMap(SortedMap p0){ return null; } + public static SortedMap transformedSortedMap(SortedMap p0, Transformer p1, Transformer p2){ return null; } + public static SortedMap unmodifiableSortedMap(SortedMap p0){ return null; } + public static V getObject(Map p0, K p1){ return null; } + public static V getObject(Map p0, K p1, V p2){ return null; } + public static void populateMap(Map p0, Iterable p1, Transformer p2){} + public static void populateMap(MultiMap p0, Iterable p1, Transformer p2){} + public static Boolean getBoolean(Map p0, K p1){ return null; } + public static Boolean getBoolean(Map p0, K p1, Boolean p2){ return null; } + public static Byte getByte(Map p0, K p1){ return null; } + public static Byte getByte(Map p0, K p1, Byte p2){ return null; } + public static Double getDouble(Map p0, K p1){ return null; } + public static Double getDouble(Map p0, K p1, Double p2){ return null; } + public static Float getFloat(Map p0, K p1){ return null; } + public static Float getFloat(Map p0, K p1, Float p2){ return null; } + public static Integer getInteger(Map p0, K p1){ return null; } + public static Integer getInteger(Map p0, K p1, Integer p2){ return null; } + public static Long getLong(Map p0, K p1){ return null; } + public static Long getLong(Map p0, K p1, Long p2){ return null; } + public static Map getMap(Map p0, K p1){ return null; } + public static Map getMap(Map p0, K p1, Map p2){ return null; } + public static Number getNumber(Map p0, K p1){ return null; } + public static Number getNumber(Map p0, K p1, Number p2){ return null; } + public static Short getShort(Map p0, K p1){ return null; } + public static Short getShort(Map p0, K p1, Short p2){ return null; } + public static String getString(Map p0, K p1){ return null; } + public static String getString(Map p0, K p1, String p2){ return null; } + public static boolean getBooleanValue(Map p0, K p1){ return false; } + public static boolean getBooleanValue(Map p0, K p1, boolean p2){ return false; } + public static byte getByteValue(Map p0, K p1){ return 0; } + public static byte getByteValue(Map p0, K p1, byte p2){ return 0; } + public static double getDoubleValue(Map p0, K p1){ return 0; } + public static double getDoubleValue(Map p0, K p1, double p2){ return 0; } + public static float getFloatValue(Map p0, K p1){ return 0; } + public static float getFloatValue(Map p0, K p1, float p2){ return 0; } + public static int getIntValue(Map p0, K p1){ return 0; } + public static int getIntValue(Map p0, K p1, int p2){ return 0; } + public static long getLongValue(Map p0, K p1){ return 0; } + public static long getLongValue(Map p0, K p1, long p2){ return 0; } + public static short getShortValue(Map p0, K p1){ return 0; } + public static short getShortValue(Map p0, K p1, short p2){ return 0; } + public static void safeAddToMap(Map p0, K p1, Object p2){} public static Map toMap(ResourceBundle p0){ return null; } public static SortedMap EMPTY_SORTED_MAP = null; - public static boolean isEmpty(Map p0){ return false; } - public static boolean isNotEmpty(Map p0){ return false; } - public static int size(Map p0){ return 0; } - public static void debugPrint(PrintStream p0, Object p1, Map p2){} - public static void verbosePrint(PrintStream p0, Object p1, Map p2){} + public static boolean isEmpty(Map p0){ return false; } + public static boolean isNotEmpty(Map p0){ return false; } + public static int size(Map p0){ return 0; } + public static void debugPrint(PrintStream p0, Object p1, Map p2){} + public static void verbosePrint(PrintStream p0, Object p1, Map p2){} } diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiMapUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiMapUtils.java new file mode 100644 index 00000000000..4b1c20bbd72 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiMapUtils.java @@ -0,0 +1,29 @@ +// Generated automatically from org.apache.commons.collections4.MultiMapUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import org.apache.commons.collections4.Bag; +import org.apache.commons.collections4.ListValuedMap; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.SetValuedMap; +import org.apache.commons.collections4.Transformer; + +public class MultiMapUtils +{ + protected MultiMapUtils() {} + public static Bag getValuesAsBag(MultiValuedMap p0, K p1){ return null; } + public static Collection getCollection(MultiValuedMap p0, K p1){ return null; } + public static List getValuesAsList(MultiValuedMap p0, K p1){ return null; } + public static ListValuedMap newListValuedHashMap(){ return null; } + public static MultiValuedMap emptyIfNull(MultiValuedMap p0){ return null; } + public static MultiValuedMap emptyMultiValuedMap(){ return null; } + public static MultiValuedMap transformedMultiValuedMap(MultiValuedMap p0, Transformer p1, Transformer p2){ return null; } + public static MultiValuedMap unmodifiableMultiValuedMap(MultiValuedMap p0){ return null; } + public static Set getValuesAsSet(MultiValuedMap p0, K p1){ return null; } + public static SetValuedMap newSetValuedHashMap(){ return null; } + public static MultiValuedMap EMPTY_MULTI_VALUED_MAP = null; + public static boolean isEmpty(MultiValuedMap p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSet.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSet.java new file mode 100644 index 00000000000..fc5adc644f3 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSet.java @@ -0,0 +1,33 @@ +// Generated automatically from org.apache.commons.collections4.MultiSet for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public interface MultiSet extends Collection +{ + Iterator iterator(); + Set uniqueSet(); + Set> entrySet(); + boolean add(E p0); + boolean containsAll(Collection p0); + boolean equals(Object p0); + boolean remove(Object p0); + boolean removeAll(Collection p0); + boolean retainAll(Collection p0); + int add(E p0, int p1); + int getCount(Object p0); + int hashCode(); + int remove(Object p0, int p1); + int setCount(E p0, int p1); + int size(); + static public interface Entry + { + E getElement(); + boolean equals(Object p0); + int getCount(); + int hashCode(); + } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSetUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSetUtils.java new file mode 100644 index 00000000000..2e996f92065 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiSetUtils.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.collections4.MultiSetUtils for testing purposes + +package org.apache.commons.collections4; + +import org.apache.commons.collections4.MultiSet; +import org.apache.commons.collections4.Predicate; + +public class MultiSetUtils +{ + protected MultiSetUtils() {} + public static MultiSet emptyMultiSet(){ return null; } + public static MultiSet predicatedMultiSet(MultiSet p0, Predicate p1){ return null; } + public static MultiSet synchronizedMultiSet(MultiSet p0){ return null; } + public static MultiSet unmodifiableMultiSet(MultiSet p0){ return null; } + public static MultiSet EMPTY_MULTISET = null; +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiValuedMap.java new file mode 100644 index 00000000000..a247d8a4258 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/MultiValuedMap.java @@ -0,0 +1,32 @@ +// Generated automatically from org.apache.commons.collections4.MultiValuedMap for testing purposes + +package org.apache.commons.collections4; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.MapIterator; +import org.apache.commons.collections4.MultiSet; + +public interface MultiValuedMap +{ + Collection> entries(); + Collection get(K p0); + Collection remove(Object p0); + Collection values(); + Map> asMap(); + MapIterator mapIterator(); + MultiSet keys(); + Set keySet(); + boolean containsKey(Object p0); + boolean containsMapping(Object p0, Object p1); + boolean containsValue(Object p0); + boolean isEmpty(); + boolean put(K p0, V p1); + boolean putAll(K p0, Iterable p1); + boolean putAll(Map p0); + boolean putAll(MultiValuedMap p0); + boolean removeMapping(Object p0, Object p1); + int size(); + void clear(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/OrderedBidiMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/OrderedBidiMap.java new file mode 100644 index 00000000000..953c13ed8f0 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/OrderedBidiMap.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.collections4.OrderedBidiMap for testing purposes + +package org.apache.commons.collections4; + +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.OrderedMap; + +public interface OrderedBidiMap extends BidiMap, OrderedMap +{ + OrderedBidiMap inverseBidiMap(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/QueueUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/QueueUtils.java new file mode 100644 index 00000000000..21cdad6cb09 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/QueueUtils.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.commons.collections4.QueueUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Queue; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class QueueUtils +{ + protected QueueUtils() {} + public static Queue emptyQueue(){ return null; } + public static Queue predicatedQueue(Queue p0, Predicate p1){ return null; } + public static Queue synchronizedQueue(Queue p0){ return null; } + public static Queue transformingQueue(Queue p0, Transformer p1){ return null; } + public static Queue unmodifiableQueue(Queue p0){ return null; } + public static Queue EMPTY_QUEUE = null; +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableIterator.java new file mode 100644 index 00000000000..6d46db71e0b --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableIterator.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.commons.collections4.ResettableIterator for testing purposes + +package org.apache.commons.collections4; + +import java.util.Iterator; + +public interface ResettableIterator extends Iterator +{ + void reset(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableListIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableListIterator.java new file mode 100644 index 00000000000..98ea868abde --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/ResettableListIterator.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.collections4.ResettableListIterator for testing purposes + +package org.apache.commons.collections4; + +import java.util.ListIterator; +import org.apache.commons.collections4.OrderedIterator; +import org.apache.commons.collections4.ResettableIterator; + +public interface ResettableListIterator extends ListIterator, OrderedIterator, ResettableIterator +{ +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetUtils.java new file mode 100644 index 00000000000..9e32be9547a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetUtils.java @@ -0,0 +1,52 @@ +// Generated automatically from org.apache.commons.collections4.SetUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedSet; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.collections4.Transformer; + +public class SetUtils +{ + protected SetUtils() {} + abstract static public class SetView extends AbstractSet + { + protected abstract Iterator createIterator(); + public > void copyInto(S p0){} + public Iterator iterator(){ return null; } + public Set toSet(){ return null; } + public SetView(){} + public int size(){ return 0; } + } + public static HashSet hashSet(E... p0){ return null; } + public static Set emptySet(){ return null; } + public static Set newIdentityHashSet(){ return null; } + public static Set orderedSet(Set p0){ return null; } + public static Set predicatedSet(Set p0, Predicate p1){ return null; } + public static Set synchronizedSet(Set p0){ return null; } + public static Set transformedSet(Set p0, Transformer p1){ return null; } + public static Set unmodifiableSet(E... p0){ return null; } + public static Set unmodifiableSet(Set p0){ return null; } + public static SetUtils.SetView difference(Set p0, Set p1){ return null; } + public static SetUtils.SetView disjunction(Set p0, Set p1){ return null; } + public static SetUtils.SetView intersection(Set p0, Set p1){ return null; } + public static SetUtils.SetView union(Set p0, Set p1){ return null; } + public static SortedSet emptySortedSet(){ return null; } + public static SortedSet predicatedNavigableSet(NavigableSet p0, Predicate p1){ return null; } + public static SortedSet predicatedSortedSet(SortedSet p0, Predicate p1){ return null; } + public static SortedSet synchronizedSortedSet(SortedSet p0){ return null; } + public static SortedSet transformedNavigableSet(NavigableSet p0, Transformer p1){ return null; } + public static SortedSet transformedSortedSet(SortedSet p0, Transformer p1){ return null; } + public static SortedSet unmodifiableNavigableSet(NavigableSet p0){ return null; } + public static SortedSet unmodifiableSortedSet(SortedSet p0){ return null; } + public static Set emptyIfNull(Set p0){ return null; } + public static int hashCodeForSet(Collection p0){ return 0; } + public static SortedSet EMPTY_SORTED_SET = null; + public static boolean isEqualSet(Collection p0, Collection p1){ return false; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetValuedMap.java new file mode 100644 index 00000000000..e46c86afc16 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SetValuedMap.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.collections4.SetValuedMap for testing purposes + +package org.apache.commons.collections4; + +import java.util.Set; +import org.apache.commons.collections4.MultiValuedMap; + +public interface SetValuedMap extends MultiValuedMap +{ + Set get(K p0); + Set remove(Object p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SortedBag.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SortedBag.java new file mode 100644 index 00000000000..5d8ee43a7e9 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SortedBag.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.commons.collections4.SortedBag for testing purposes + +package org.apache.commons.collections4; + +import java.util.Comparator; +import org.apache.commons.collections4.Bag; + +public interface SortedBag extends Bag +{ + Comparator comparator(); + E first(); + E last(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SplitMapUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SplitMapUtils.java new file mode 100644 index 00000000000..4274ec4e950 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/SplitMapUtils.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.commons.collections4.SplitMapUtils for testing purposes + +package org.apache.commons.collections4; + +import java.util.Map; +import org.apache.commons.collections4.Get; +import org.apache.commons.collections4.IterableMap; +import org.apache.commons.collections4.Put; + +public class SplitMapUtils +{ + protected SplitMapUtils() {} + public static IterableMap readableMap(Get p0){ return null; } + public static Map writableMap(Put p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Trie.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Trie.java new file mode 100644 index 00000000000..cfd130d054f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/Trie.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.collections4.Trie for testing purposes + +package org.apache.commons.collections4; + +import java.util.SortedMap; +import org.apache.commons.collections4.IterableSortedMap; + +public interface Trie extends IterableSortedMap +{ + SortedMap prefixMap(K p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/TrieUtils.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/TrieUtils.java new file mode 100644 index 00000000000..ee8cfe40a85 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/TrieUtils.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.collections4.TrieUtils for testing purposes + +package org.apache.commons.collections4; + +import org.apache.commons.collections4.Trie; + +public class TrieUtils +{ + protected TrieUtils() {} + public static Trie unmodifiableTrie(Trie p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/AbstractMapBag.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/AbstractMapBag.java new file mode 100644 index 00000000000..78374820036 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/AbstractMapBag.java @@ -0,0 +1,50 @@ +// Generated automatically from org.apache.commons.collections4.bag.AbstractMapBag for testing purposes + +package org.apache.commons.collections4.bag; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.Bag; + +abstract public class AbstractMapBag implements Bag +{ + boolean containsAll(Bag p0){ return false; } + boolean retainAll(Bag p0){ return false; } + protected AbstractMapBag(){} + protected AbstractMapBag(Map p0){} + protected Map getMap(){ return null; } + protected void doReadObject(Map p0, ObjectInputStream p1){} + protected void doWriteObject(ObjectOutputStream p0){} + public T[] toArray(T[] p0){ return null; } + public Iterator iterator(){ return null; } + public Object[] toArray(){ return null; } + public Set uniqueSet(){ return null; } + public String toString(){ return null; } + public boolean add(E p0){ return false; } + public boolean add(E p0, int p1){ return false; } + public boolean addAll(Collection p0){ return false; } + public boolean contains(Object p0){ return false; } + public boolean containsAll(Collection p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean remove(Object p0){ return false; } + public boolean remove(Object p0, int p1){ return false; } + public boolean removeAll(Collection p0){ return false; } + public boolean retainAll(Collection p0){ return false; } + public int getCount(Object p0){ return 0; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public void clear(){} + static class MutableInteger + { + protected MutableInteger() {} + MutableInteger(int p0){} + protected int value = 0; + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/TreeBag.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/TreeBag.java new file mode 100644 index 00000000000..3dbe40b6776 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bag/TreeBag.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.commons.collections4.bag.TreeBag for testing purposes + +package org.apache.commons.collections4.bag; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.SortedMap; +import org.apache.commons.collections4.SortedBag; +import org.apache.commons.collections4.bag.AbstractMapBag; + +public class TreeBag extends AbstractMapBag implements Serializable, SortedBag +{ + protected SortedMap getMap(){ return null; } + public Comparator comparator(){ return null; } + public E first(){ return null; } + public E last(){ return null; } + public TreeBag(){} + public TreeBag(Collection p0){} + public TreeBag(Comparator p0){} + public boolean add(E p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bidimap/TreeBidiMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bidimap/TreeBidiMap.java new file mode 100644 index 00000000000..3850478cef0 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/bidimap/TreeBidiMap.java @@ -0,0 +1,38 @@ +// Generated automatically from org.apache.commons.collections4.bidimap.TreeBidiMap for testing purposes + +package org.apache.commons.collections4.bidimap; + +import java.io.Serializable; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.OrderedBidiMap; +import org.apache.commons.collections4.OrderedMapIterator; + +public class TreeBidiMap, V extends Comparable> implements OrderedBidiMap, Serializable +{ + public K firstKey(){ return null; } + public K getKey(Object p0){ return null; } + public K lastKey(){ return null; } + public K nextKey(K p0){ return null; } + public K previousKey(K p0){ return null; } + public K removeValue(Object p0){ return null; } + public OrderedBidiMap inverseBidiMap(){ return null; } + public OrderedMapIterator mapIterator(){ return null; } + public Set keySet(){ return null; } + public Set> entrySet(){ return null; } + public Set values(){ return null; } + public String toString(){ return null; } + public TreeBidiMap(){} + public TreeBidiMap(Map p0){} + public V get(Object p0){ return null; } + public V put(K p0, V p1){ return null; } + public V remove(Object p0){ return null; } + public boolean containsKey(Object p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public void clear(){} + public void putAll(Map p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractIteratorDecorator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractIteratorDecorator.java new file mode 100644 index 00000000000..01491338b7a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractIteratorDecorator.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.commons.collections4.iterators.AbstractIteratorDecorator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; +import org.apache.commons.collections4.iterators.AbstractUntypedIteratorDecorator; + +abstract public class AbstractIteratorDecorator extends AbstractUntypedIteratorDecorator +{ + protected AbstractIteratorDecorator() {} + protected AbstractIteratorDecorator(Iterator p0){} + public E next(){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractUntypedIteratorDecorator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractUntypedIteratorDecorator.java new file mode 100644 index 00000000000..a29981467bd --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/AbstractUntypedIteratorDecorator.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.commons.collections4.iterators.AbstractUntypedIteratorDecorator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; + +abstract public class AbstractUntypedIteratorDecorator implements Iterator +{ + protected AbstractUntypedIteratorDecorator() {} + protected AbstractUntypedIteratorDecorator(Iterator p0){} + protected Iterator getIterator(){ return null; } + public boolean hasNext(){ return false; } + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/BoundedIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/BoundedIterator.java new file mode 100644 index 00000000000..d45ff0f7564 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/BoundedIterator.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.commons.collections4.iterators.BoundedIterator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; + +public class BoundedIterator implements Iterator +{ + protected BoundedIterator() {} + public BoundedIterator(Iterator p0, long p1, long p2){} + public E next(){ return null; } + public boolean hasNext(){ return false; } + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/IteratorEnumeration.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/IteratorEnumeration.java new file mode 100644 index 00000000000..13b1ca42ace --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/IteratorEnumeration.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.collections4.iterators.IteratorEnumeration for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Enumeration; +import java.util.Iterator; + +public class IteratorEnumeration implements Enumeration +{ + public E nextElement(){ return null; } + public Iterator getIterator(){ return null; } + public IteratorEnumeration(){} + public IteratorEnumeration(Iterator p0){} + public boolean hasMoreElements(){ return false; } + public void setIterator(Iterator p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/NodeListIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/NodeListIterator.java new file mode 100644 index 00000000000..6431ab905a5 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/NodeListIterator.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.commons.collections4.iterators.NodeListIterator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class NodeListIterator implements Iterator +{ + protected NodeListIterator() {} + public Node next(){ return null; } + public NodeListIterator(Node p0){} + public NodeListIterator(NodeList p0){} + public boolean hasNext(){ return false; } + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/SkippingIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/SkippingIterator.java new file mode 100644 index 00000000000..b83e97b23e1 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/SkippingIterator.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.commons.collections4.iterators.SkippingIterator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; +import org.apache.commons.collections4.iterators.AbstractIteratorDecorator; + +public class SkippingIterator extends AbstractIteratorDecorator +{ + protected SkippingIterator() {} + public E next(){ return null; } + public SkippingIterator(Iterator p0, long p1){} + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/ZippingIterator.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/ZippingIterator.java new file mode 100644 index 00000000000..2d722327f70 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/iterators/ZippingIterator.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.collections4.iterators.ZippingIterator for testing purposes + +package org.apache.commons.collections4.iterators; + +import java.util.Iterator; + +public class ZippingIterator implements Iterator +{ + protected ZippingIterator() {} + public E next(){ return null; } + public ZippingIterator(Iterator p0, Iterator p1){} + public ZippingIterator(Iterator p0, Iterator p1, Iterator p2){} + public ZippingIterator(Iterator... p0){} + public boolean hasNext(){ return false; } + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/DefaultMapEntry.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/DefaultMapEntry.java index 5fd732d592f..e05f7698a9a 100644 --- a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/DefaultMapEntry.java +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/DefaultMapEntry.java @@ -12,6 +12,4 @@ public class DefaultMapEntry extends AbstractMapEntry public DefaultMapEntry(K p0, V p1){} public DefaultMapEntry(KeyValue p0){} public DefaultMapEntry(Map.Entry p0){} - public V getValue(){ return null; } - public K getKey(){ return null; } } diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/UnmodifiableMapEntry.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/UnmodifiableMapEntry.java index 2db2edab16f..20bd8a0880d 100644 --- a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/UnmodifiableMapEntry.java +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/keyvalue/UnmodifiableMapEntry.java @@ -14,6 +14,4 @@ public class UnmodifiableMapEntry extends AbstractMapEntry implement public UnmodifiableMapEntry(KeyValue p0){} public UnmodifiableMapEntry(Map.Entry p0){} public V setValue(V p0){ return null; } - public V getValue(){ return null; } - public K getKey(){ return null; } } diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractHashedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractHashedMap.java new file mode 100644 index 00000000000..f79236e4f10 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractHashedMap.java @@ -0,0 +1,133 @@ +// Generated automatically from org.apache.commons.collections4.map.AbstractHashedMap for testing purposes + +package org.apache.commons.collections4.map; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.IterableMap; +import org.apache.commons.collections4.KeyValue; +import org.apache.commons.collections4.MapIterator; + +public class AbstractHashedMap extends AbstractMap implements IterableMap +{ + AbstractHashedMap.EntrySet entrySet = null; + AbstractHashedMap.HashEntry[] data = null; + AbstractHashedMap.KeySet keySet = null; + AbstractHashedMap.Values values = null; + float loadFactor = 0; + int modCount = 0; + int size = 0; + int threshold = 0; + protected AbstractHashedMap(){} + protected AbstractHashedMap(Map p0){} + protected AbstractHashedMap(int p0){} + protected AbstractHashedMap(int p0, float p1){} + protected AbstractHashedMap(int p0, float p1, int p2){} + protected AbstractHashedMap.HashEntry createEntry(AbstractHashedMap.HashEntry p0, int p1, K p2, V p3){ return null; } + protected AbstractHashedMap.HashEntry entryNext(AbstractHashedMap.HashEntry p0){ return null; } + protected AbstractHashedMap.HashEntry getEntry(Object p0){ return null; } + protected AbstractHashedMap clone(){ return null; } + protected Iterator createKeySetIterator(){ return null; } + protected Iterator> createEntrySetIterator(){ return null; } + protected Iterator createValuesIterator(){ return null; } + protected K entryKey(AbstractHashedMap.HashEntry p0){ return null; } + protected Object convertKey(Object p0){ return null; } + protected V entryValue(AbstractHashedMap.HashEntry p0){ return null; } + protected boolean isEqualKey(Object p0, Object p1){ return false; } + protected boolean isEqualValue(Object p0, Object p1){ return false; } + protected int calculateNewCapacity(int p0){ return 0; } + protected int calculateThreshold(int p0, float p1){ return 0; } + protected int entryHashCode(AbstractHashedMap.HashEntry p0){ return 0; } + protected int hash(Object p0){ return 0; } + protected int hashIndex(int p0, int p1){ return 0; } + protected static Object NULL = null; + protected static String GETKEY_INVALID = null; + protected static String GETVALUE_INVALID = null; + protected static String NO_NEXT_ENTRY = null; + protected static String NO_PREVIOUS_ENTRY = null; + protected static String REMOVE_INVALID = null; + protected static String SETVALUE_INVALID = null; + protected static float DEFAULT_LOAD_FACTOR = 0; + protected static int DEFAULT_CAPACITY = 0; + protected static int DEFAULT_THRESHOLD = 0; + protected static int MAXIMUM_CAPACITY = 0; + protected void addEntry(AbstractHashedMap.HashEntry p0, int p1){} + protected void addMapping(int p0, int p1, K p2, V p3){} + protected void checkCapacity(){} + protected void destroyEntry(AbstractHashedMap.HashEntry p0){} + protected void doReadObject(ObjectInputStream p0){} + protected void doWriteObject(ObjectOutputStream p0){} + protected void ensureCapacity(int p0){} + protected void init(){} + protected void removeEntry(AbstractHashedMap.HashEntry p0, int p1, AbstractHashedMap.HashEntry p2){} + protected void removeMapping(AbstractHashedMap.HashEntry p0, int p1, AbstractHashedMap.HashEntry p2){} + protected void reuseEntry(AbstractHashedMap.HashEntry p0, int p1, int p2, K p3, V p4){} + protected void updateEntry(AbstractHashedMap.HashEntry p0, V p1){} + public Collection values(){ return null; } + public MapIterator mapIterator(){ return null; } + public Set keySet(){ return null; } + public Set> entrySet(){ return null; } + public String toString(){ return null; } + public V get(Object p0){ return null; } + public V put(K p0, V p1){ return null; } + public V remove(Object p0){ return null; } + public boolean containsKey(Object p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public void clear(){} + public void putAll(Map p0){} + static class EntrySet extends AbstractSet> + { + protected EntrySet() {} + protected EntrySet(AbstractHashedMap p0){} + public Iterator> iterator(){ return null; } + public boolean contains(Object p0){ return false; } + public boolean remove(Object p0){ return false; } + public int size(){ return 0; } + public void clear(){} + } + static class HashEntry implements KeyValue, Map.Entry + { + protected HashEntry() {} + protected AbstractHashedMap.HashEntry next = null; + protected HashEntry(AbstractHashedMap.HashEntry p0, int p1, Object p2, V p3){} + protected Object key = null; + protected Object value = null; + protected int hashCode = 0; + public K getKey(){ return null; } + public String toString(){ return null; } + public V getValue(){ return null; } + public V setValue(V p0){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + } + static class KeySet extends AbstractSet + { + protected KeySet() {} + protected KeySet(AbstractHashedMap p0){} + public Iterator iterator(){ return null; } + public boolean contains(Object p0){ return false; } + public boolean remove(Object p0){ return false; } + public int size(){ return 0; } + public void clear(){} + } + static class Values extends AbstractCollection + { + protected Values() {} + protected Values(AbstractHashedMap p0){} + public Iterator iterator(){ return null; } + public boolean contains(Object p0){ return false; } + public int size(){ return 0; } + public void clear(){} + } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractLinkedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractLinkedMap.java new file mode 100644 index 00000000000..b96404dd5b9 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/AbstractLinkedMap.java @@ -0,0 +1,44 @@ +// Generated automatically from org.apache.commons.collections4.map.AbstractLinkedMap for testing purposes + +package org.apache.commons.collections4.map; + +import java.util.Iterator; +import java.util.Map; +import org.apache.commons.collections4.OrderedMap; +import org.apache.commons.collections4.OrderedMapIterator; +import org.apache.commons.collections4.map.AbstractHashedMap; + +abstract public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap +{ + AbstractLinkedMap.LinkEntry header = null; + protected AbstractLinkedMap(){} + protected AbstractLinkedMap(Map p0){} + protected AbstractLinkedMap(int p0){} + protected AbstractLinkedMap(int p0, float p1){} + protected AbstractLinkedMap(int p0, float p1, int p2){} + protected AbstractLinkedMap.LinkEntry createEntry(AbstractHashedMap.HashEntry p0, int p1, K p2, V p3){ return null; } + protected AbstractLinkedMap.LinkEntry entryAfter(AbstractLinkedMap.LinkEntry p0){ return null; } + protected AbstractLinkedMap.LinkEntry entryBefore(AbstractLinkedMap.LinkEntry p0){ return null; } + protected AbstractLinkedMap.LinkEntry getEntry(Object p0){ return null; } + protected AbstractLinkedMap.LinkEntry getEntry(int p0){ return null; } + protected Iterator createKeySetIterator(){ return null; } + protected Iterator> createEntrySetIterator(){ return null; } + protected Iterator createValuesIterator(){ return null; } + protected void addEntry(AbstractHashedMap.HashEntry p0, int p1){} + protected void init(){} + protected void removeEntry(AbstractHashedMap.HashEntry p0, int p1, AbstractHashedMap.HashEntry p2){} + public K firstKey(){ return null; } + public K lastKey(){ return null; } + public K nextKey(Object p0){ return null; } + public K previousKey(Object p0){ return null; } + public OrderedMapIterator mapIterator(){ return null; } + public boolean containsValue(Object p0){ return false; } + public void clear(){} + static class LinkEntry extends AbstractHashedMap.HashEntry + { + protected LinkEntry() {} + protected AbstractLinkedMap.LinkEntry after = null; + protected AbstractLinkedMap.LinkEntry before = null; + protected LinkEntry(AbstractHashedMap.HashEntry p0, int p1, Object p2, V p3){} + } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/HashedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/HashedMap.java new file mode 100644 index 00000000000..c2e71aa2da7 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/HashedMap.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.collections4.map.HashedMap for testing purposes + +package org.apache.commons.collections4.map; + +import java.io.Serializable; +import java.util.Map; +import org.apache.commons.collections4.map.AbstractHashedMap; + +public class HashedMap extends AbstractHashedMap implements Cloneable, Serializable +{ + public HashedMap(){} + public HashedMap(Map p0){} + public HashedMap(int p0){} + public HashedMap(int p0, float p1){} + public HashedMap clone(){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/LinkedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/LinkedMap.java new file mode 100644 index 00000000000..51740715e05 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/LinkedMap.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.commons.collections4.map.LinkedMap for testing purposes + +package org.apache.commons.collections4.map; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.map.AbstractLinkedMap; + +public class LinkedMap extends AbstractLinkedMap implements Cloneable, Serializable +{ + public K get(int p0){ return null; } + public LinkedMap(){} + public LinkedMap(Map p0){} + public LinkedMap(int p0){} + public LinkedMap(int p0, float p1){} + public LinkedMap clone(){ return null; } + public List asList(){ return null; } + public V getValue(int p0){ return null; } + public V remove(int p0){ return null; } + public int indexOf(Object p0){ return 0; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/MultiValueMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/MultiValueMap.java index b09b192b942..5a99e41f9b5 100644 --- a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/MultiValueMap.java +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/map/MultiValueMap.java @@ -13,8 +13,8 @@ import org.apache.commons.collections4.map.AbstractMapDecorator; public class MultiValueMap extends AbstractMapDecorator implements MultiMap, Serializable { + protected > MultiValueMap(Map p0, Factory p1){} protected Collection createCollection(int p0){ return null; } - protected MultiValueMap(Map p0, Factory p1){} public Collection values(){ return null; } public Collection getCollection(Object p0){ return null; } public Iterator> iterator(){ return null; } @@ -28,13 +28,9 @@ public class MultiValueMap extends AbstractMapDecorator impleme public boolean removeMapping(Object p0, Object p1){ return false; } public int size(Object p0){ return 0; } public int totalSize(){ return 0; } - public static MultiValueMap multiValueMap(Map p0, Class p1){ return null; } - public static MultiValueMap multiValueMap(Map p0, Factory p1){ return null; } - public static MultiValueMap multiValueMap(Map> p0){ return null; } + public static > MultiValueMap multiValueMap(Map p0, Class p1){ return null; } + public static > MultiValueMap multiValueMap(Map p0, Factory p1){ return null; } + public static MultiValueMap multiValueMap(Map> p0){ return null; } public void clear(){} - public void putAll(Map p0){} - public int size(){ return 0; } - public Object remove(Object key){ return null; } - public Object get(Object key){ return null; } - public boolean isEmpty(){ return false; } + public void putAll(Map p0){} } diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractListValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractListValuedMap.java new file mode 100644 index 00000000000..599411c5a87 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractListValuedMap.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.commons.collections4.multimap.AbstractListValuedMap for testing purposes + +package org.apache.commons.collections4.multimap; + +import java.util.List; +import java.util.Map; +import org.apache.commons.collections4.ListValuedMap; +import org.apache.commons.collections4.multimap.AbstractMultiValuedMap; + +abstract public class AbstractListValuedMap extends AbstractMultiValuedMap implements ListValuedMap +{ + List wrappedCollection(K p0){ return null; } + protected AbstractListValuedMap(){} + protected AbstractListValuedMap(Map> p0){} + protected Map> getMap(){ return null; } + protected abstract List createCollection(); + public List get(K p0){ return null; } + public List remove(Object p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java new file mode 100644 index 00000000000..b86762b580f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java @@ -0,0 +1,46 @@ +// Generated automatically from org.apache.commons.collections4.multimap.AbstractMultiValuedMap for testing purposes + +package org.apache.commons.collections4.multimap; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.MapIterator; +import org.apache.commons.collections4.MultiSet; +import org.apache.commons.collections4.MultiValuedMap; + +abstract public class AbstractMultiValuedMap implements MultiValuedMap +{ + Collection wrappedCollection(K p0){ return null; } + protected AbstractMultiValuedMap(){} + protected AbstractMultiValuedMap(Map> p0){} + protected Map> getMap(){ return null; } + protected abstract Collection createCollection(); + protected void doReadObject(ObjectInputStream p0){} + protected void doWriteObject(ObjectOutputStream p0){} + protected void setMap(Map> p0){} + public Collection> entries(){ return null; } + public Collection get(K p0){ return null; } + public Collection remove(Object p0){ return null; } + public Collection values(){ return null; } + public Map> asMap(){ return null; } + public MapIterator mapIterator(){ return null; } + public MultiSet keys(){ return null; } + public Set keySet(){ return null; } + public String toString(){ return null; } + public boolean containsKey(Object p0){ return false; } + public boolean containsMapping(Object p0, Object p1){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean put(K p0, V p1){ return false; } + public boolean putAll(K p0, Iterable p1){ return false; } + public boolean putAll(Map p0){ return false; } + public boolean putAll(MultiValuedMap p0){ return false; } + public boolean removeMapping(Object p0, Object p1){ return false; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public void clear(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java new file mode 100644 index 00000000000..feae9379a4e --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.commons.collections4.multimap.AbstractSetValuedMap for testing purposes + +package org.apache.commons.collections4.multimap; + +import java.util.Map; +import java.util.Set; +import org.apache.commons.collections4.SetValuedMap; +import org.apache.commons.collections4.multimap.AbstractMultiValuedMap; + +abstract public class AbstractSetValuedMap extends AbstractMultiValuedMap implements SetValuedMap +{ + Set wrappedCollection(K p0){ return null; } + protected AbstractSetValuedMap(){} + protected AbstractSetValuedMap(Map> p0){} + protected Map> getMap(){ return null; } + protected abstract Set createCollection(); + public Set get(K p0){ return null; } + public Set remove(Object p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java new file mode 100644 index 00000000000..d02ec3a711e --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.commons.collections4.multimap.ArrayListValuedHashMap for testing purposes + +package org.apache.commons.collections4.multimap; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Map; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.multimap.AbstractListValuedMap; + +public class ArrayListValuedHashMap extends AbstractListValuedMap implements Serializable +{ + protected ArrayList createCollection(){ return null; } + public ArrayListValuedHashMap(){} + public ArrayListValuedHashMap(Map p0){} + public ArrayListValuedHashMap(MultiValuedMap p0){} + public ArrayListValuedHashMap(int p0){} + public ArrayListValuedHashMap(int p0, int p1){} + public void trimToSize(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java new file mode 100644 index 00000000000..c7ae3ab48de --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.commons.collections4.multimap.HashSetValuedHashMap for testing purposes + +package org.apache.commons.collections4.multimap; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Map; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.multimap.AbstractSetValuedMap; + +public class HashSetValuedHashMap extends AbstractSetValuedMap implements Serializable +{ + protected HashSet createCollection(){ return null; } + public HashSetValuedHashMap(){} + public HashSetValuedHashMap(Map p0){} + public HashSetValuedHashMap(MultiValuedMap p0){} + public HashSetValuedHashMap(int p0){} + public HashSetValuedHashMap(int p0, int p1){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMapMultiSet.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMapMultiSet.java new file mode 100644 index 00000000000..922994f94f5 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMapMultiSet.java @@ -0,0 +1,43 @@ +// Generated automatically from org.apache.commons.collections4.multiset.AbstractMapMultiSet for testing purposes + +package org.apache.commons.collections4.multiset; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Iterator; +import java.util.Map; +import org.apache.commons.collections4.MultiSet; +import org.apache.commons.collections4.multiset.AbstractMultiSet; + +abstract public class AbstractMapMultiSet extends AbstractMultiSet +{ + protected AbstractMapMultiSet(){} + protected AbstractMapMultiSet(Map p0){} + protected Iterator createUniqueSetIterator(){ return null; } + protected Iterator> createEntrySetIterator(){ return null; } + protected Map getMap(){ return null; } + protected int uniqueElements(){ return 0; } + protected void doReadObject(ObjectInputStream p0){} + protected void doWriteObject(ObjectOutputStream p0){} + protected void setMap(Map p0){} + public T[] toArray(T[] p0){ return null; } + public Iterator iterator(){ return null; } + public Object[] toArray(){ return null; } + public boolean contains(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int add(E p0, int p1){ return 0; } + public int getCount(Object p0){ return 0; } + public int hashCode(){ return 0; } + public int remove(Object p0, int p1){ return 0; } + public int size(){ return 0; } + public void clear(){} + static class MutableInteger + { + protected MutableInteger() {} + MutableInteger(int p0){} + protected int value = 0; + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMultiSet.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMultiSet.java new file mode 100644 index 00000000000..9c6b816532e --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/AbstractMultiSet.java @@ -0,0 +1,39 @@ +// Generated automatically from org.apache.commons.collections4.multiset.AbstractMultiSet for testing purposes + +package org.apache.commons.collections4.multiset; + +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import org.apache.commons.collections4.MultiSet; + +abstract public class AbstractMultiSet extends AbstractCollection implements MultiSet +{ + protected AbstractMultiSet(){} + protected Iterator createUniqueSetIterator(){ return null; } + protected Set createUniqueSet(){ return null; } + protected Set> createEntrySet(){ return null; } + protected abstract Iterator> createEntrySetIterator(); + protected abstract int uniqueElements(); + protected void doReadObject(ObjectInputStream p0){} + protected void doWriteObject(ObjectOutputStream p0){} + public Iterator iterator(){ return null; } + public Set uniqueSet(){ return null; } + public Set> entrySet(){ return null; } + public String toString(){ return null; } + public boolean add(E p0){ return false; } + public boolean contains(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean remove(Object p0){ return false; } + public boolean removeAll(Collection p0){ return false; } + public int add(E p0, int p1){ return 0; } + public int getCount(Object p0){ return 0; } + public int hashCode(){ return 0; } + public int remove(Object p0, int p1){ return 0; } + public int setCount(E p0, int p1){ return 0; } + public int size(){ return 0; } + public void clear(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/HashMultiSet.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/HashMultiSet.java new file mode 100644 index 00000000000..9337a372adb --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/multiset/HashMultiSet.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.commons.collections4.multiset.HashMultiSet for testing purposes + +package org.apache.commons.collections4.multiset; + +import java.io.Serializable; +import java.util.Collection; +import org.apache.commons.collections4.multiset.AbstractMapMultiSet; + +public class HashMultiSet extends AbstractMapMultiSet implements Serializable +{ + public HashMultiSet(){} + public HashMultiSet(Collection p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractBitwiseTrie.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractBitwiseTrie.java new file mode 100644 index 00000000000..5ed4dfda241 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractBitwiseTrie.java @@ -0,0 +1,39 @@ +// Generated automatically from org.apache.commons.collections4.trie.AbstractBitwiseTrie for testing purposes + +package org.apache.commons.collections4.trie; + +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Map; +import org.apache.commons.collections4.Trie; +import org.apache.commons.collections4.trie.KeyAnalyzer; + +abstract public class AbstractBitwiseTrie extends AbstractMap implements Serializable, Trie +{ + protected AbstractBitwiseTrie() {} + abstract static class BasicEntry implements Map.Entry, Serializable + { + protected BasicEntry() {} + protected K key = null; + protected V value = null; + public BasicEntry(K p0){} + public BasicEntry(K p0, V p1){} + public K getKey(){ return null; } + public String toString(){ return null; } + public V getValue(){ return null; } + public V setKeyValue(K p0, V p1){ return null; } + public V setValue(V p0){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + } + final K castKey(Object p0){ return null; } + final boolean compareKeys(K p0, K p1){ return false; } + final boolean isBitSet(K p0, int p1, int p2){ return false; } + final int bitIndex(K p0, K p1){ return 0; } + final int bitsPerElement(){ return 0; } + final int lengthInBits(K p0){ return 0; } + protected AbstractBitwiseTrie(KeyAnalyzer p0){} + protected KeyAnalyzer getKeyAnalyzer(){ return null; } + public String toString(){ return null; } + static boolean compare(Object p0, Object p1){ return false; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractPatriciaTrie.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractPatriciaTrie.java new file mode 100644 index 00000000000..a37ea503009 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/AbstractPatriciaTrie.java @@ -0,0 +1,76 @@ +// Generated automatically from org.apache.commons.collections4.trie.AbstractPatriciaTrie for testing purposes + +package org.apache.commons.collections4.trie; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import org.apache.commons.collections4.OrderedMapIterator; +import org.apache.commons.collections4.trie.AbstractBitwiseTrie; +import org.apache.commons.collections4.trie.KeyAnalyzer; + +abstract class AbstractPatriciaTrie extends AbstractBitwiseTrie +{ + protected AbstractPatriciaTrie() {} + AbstractPatriciaTrie.TrieEntry addEntry(AbstractPatriciaTrie.TrieEntry p0, int p1){ return null; } + AbstractPatriciaTrie.TrieEntry ceilingEntry(K p0){ return null; } + AbstractPatriciaTrie.TrieEntry firstEntry(){ return null; } + AbstractPatriciaTrie.TrieEntry floorEntry(K p0){ return null; } + AbstractPatriciaTrie.TrieEntry followLeft(AbstractPatriciaTrie.TrieEntry p0){ return null; } + AbstractPatriciaTrie.TrieEntry followRight(AbstractPatriciaTrie.TrieEntry p0){ return null; } + AbstractPatriciaTrie.TrieEntry getEntry(Object p0){ return null; } + AbstractPatriciaTrie.TrieEntry getNearestEntryForKey(K p0, int p1){ return null; } + AbstractPatriciaTrie.TrieEntry higherEntry(K p0){ return null; } + AbstractPatriciaTrie.TrieEntry lastEntry(){ return null; } + AbstractPatriciaTrie.TrieEntry lowerEntry(K p0){ return null; } + AbstractPatriciaTrie.TrieEntry nextEntry(AbstractPatriciaTrie.TrieEntry p0){ return null; } + AbstractPatriciaTrie.TrieEntry nextEntryImpl(AbstractPatriciaTrie.TrieEntry p0, AbstractPatriciaTrie.TrieEntry p1, AbstractPatriciaTrie.TrieEntry p2){ return null; } + AbstractPatriciaTrie.TrieEntry nextEntryInSubtree(AbstractPatriciaTrie.TrieEntry p0, AbstractPatriciaTrie.TrieEntry p1){ return null; } + AbstractPatriciaTrie.TrieEntry previousEntry(AbstractPatriciaTrie.TrieEntry p0){ return null; } + AbstractPatriciaTrie.TrieEntry subtree(K p0, int p1, int p2){ return null; } + V removeEntry(AbstractPatriciaTrie.TrieEntry p0){ return null; } + protected AbstractPatriciaTrie(KeyAnalyzer p0){} + protected AbstractPatriciaTrie(KeyAnalyzer p0, Map p1){} + protected int modCount = 0; + public Collection values(){ return null; } + public Comparator comparator(){ return null; } + public K firstKey(){ return null; } + public K lastKey(){ return null; } + public K nextKey(K p0){ return null; } + public K previousKey(K p0){ return null; } + public K selectKey(K p0){ return null; } + public Map.Entry select(K p0){ return null; } + public OrderedMapIterator mapIterator(){ return null; } + public Set keySet(){ return null; } + public Set> entrySet(){ return null; } + public SortedMap headMap(K p0){ return null; } + public SortedMap prefixMap(K p0){ return null; } + public SortedMap subMap(K p0, K p1){ return null; } + public SortedMap tailMap(K p0){ return null; } + public V get(Object p0){ return null; } + public V put(K p0, V p1){ return null; } + public V remove(Object p0){ return null; } + public V selectValue(K p0){ return null; } + public boolean containsKey(Object p0){ return false; } + public int size(){ return 0; } + public void clear(){} + static boolean isValidUplink(AbstractPatriciaTrie.TrieEntry p0, AbstractPatriciaTrie.TrieEntry p1){ return false; } + static class TrieEntry extends AbstractBitwiseTrie.BasicEntry + { + protected TrieEntry() {} + protected AbstractPatriciaTrie.TrieEntry left = null; + protected AbstractPatriciaTrie.TrieEntry parent = null; + protected AbstractPatriciaTrie.TrieEntry predecessor = null; + protected AbstractPatriciaTrie.TrieEntry right = null; + protected int bitIndex = 0; + public String toString(){ return null; } + public TrieEntry(K p0, V p1, int p2){} + public boolean isEmpty(){ return false; } + public boolean isExternalNode(){ return false; } + public boolean isInternalNode(){ return false; } + } + void decrementSize(){} + void incrementSize(){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/KeyAnalyzer.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/KeyAnalyzer.java new file mode 100644 index 00000000000..e5d1024f1f1 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/KeyAnalyzer.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.commons.collections4.trie.KeyAnalyzer for testing purposes + +package org.apache.commons.collections4.trie; + +import java.io.Serializable; +import java.util.Comparator; + +abstract public class KeyAnalyzer implements Comparator, Serializable +{ + public KeyAnalyzer(){} + public abstract boolean isBitSet(K p0, int p1, int p2); + public abstract boolean isPrefix(K p0, int p1, int p2, K p3); + public abstract int bitIndex(K p0, int p1, int p2, K p3, int p4, int p5); + public abstract int bitsPerElement(); + public abstract int lengthInBits(K p0); + public int compare(K p0, K p1){ return 0; } + public static int EQUAL_BIT_KEY = 0; + public static int NULL_BIT_KEY = 0; + public static int OUT_OF_BOUNDS_BIT_KEY = 0; + static boolean isEqualBitKey(int p0){ return false; } + static boolean isNullBitKey(int p0){ return false; } + static boolean isOutOfBoundsIndex(int p0){ return false; } + static boolean isValidBitIndex(int p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/PatriciaTrie.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/PatriciaTrie.java new file mode 100644 index 00000000000..e5f2dfaef2a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/apache/commons/collections4/trie/PatriciaTrie.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.collections4.trie.PatriciaTrie for testing purposes + +package org.apache.commons.collections4.trie; + +import java.util.Map; +import org.apache.commons.collections4.trie.AbstractPatriciaTrie; + +public class PatriciaTrie extends AbstractPatriciaTrie +{ + public PatriciaTrie(){} + public PatriciaTrie(Map p0){} +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Attr.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Attr.java new file mode 100644 index 00000000000..51608242ec8 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Attr.java @@ -0,0 +1,18 @@ +// Generated automatically from org.w3c.dom.Attr for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.TypeInfo; + +public interface Attr extends Node +{ + Element getOwnerElement(); + String getName(); + String getValue(); + TypeInfo getSchemaTypeInfo(); + boolean getSpecified(); + boolean isId(); + void setValue(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CDATASection.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CDATASection.java new file mode 100644 index 00000000000..5285b245069 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CDATASection.java @@ -0,0 +1,9 @@ +// Generated automatically from org.w3c.dom.CDATASection for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Text; + +public interface CDATASection extends Text +{ +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CharacterData.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CharacterData.java new file mode 100644 index 00000000000..01eecd31912 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/CharacterData.java @@ -0,0 +1,17 @@ +// Generated automatically from org.w3c.dom.CharacterData for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface CharacterData extends Node +{ + String getData(); + String substringData(int p0, int p1); + int getLength(); + void appendData(String p0); + void deleteData(int p0, int p1); + void insertData(int p0, String p1); + void replaceData(int p0, int p1, String p2); + void setData(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Comment.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Comment.java new file mode 100644 index 00000000000..c1c206ce782 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Comment.java @@ -0,0 +1,9 @@ +// Generated automatically from org.w3c.dom.Comment for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.CharacterData; + +public interface Comment extends CharacterData +{ +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMConfiguration.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMConfiguration.java new file mode 100644 index 00000000000..a1025af725b --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMConfiguration.java @@ -0,0 +1,13 @@ +// Generated automatically from org.w3c.dom.DOMConfiguration for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.DOMStringList; + +public interface DOMConfiguration +{ + DOMStringList getParameterNames(); + Object getParameter(String p0); + boolean canSetParameter(String p0, Object p1); + void setParameter(String p0, Object p1); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMImplementation.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMImplementation.java new file mode 100644 index 00000000000..398c29bdc6a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMImplementation.java @@ -0,0 +1,14 @@ +// Generated automatically from org.w3c.dom.DOMImplementation for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.DocumentType; + +public interface DOMImplementation +{ + Document createDocument(String p0, String p1, DocumentType p2); + DocumentType createDocumentType(String p0, String p1, String p2); + Object getFeature(String p0, String p1); + boolean hasFeature(String p0, String p1); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMStringList.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMStringList.java new file mode 100644 index 00000000000..ddedb943a62 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DOMStringList.java @@ -0,0 +1,11 @@ +// Generated automatically from org.w3c.dom.DOMStringList for testing purposes + +package org.w3c.dom; + + +public interface DOMStringList +{ + String item(int p0); + boolean contains(String p0); + int getLength(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Document.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Document.java new file mode 100644 index 00000000000..ce831fbdaba --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Document.java @@ -0,0 +1,52 @@ +// Generated automatically from org.w3c.dom.Document for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; + +public interface Document extends Node +{ + Attr createAttribute(String p0); + Attr createAttributeNS(String p0, String p1); + CDATASection createCDATASection(String p0); + Comment createComment(String p0); + DOMConfiguration getDomConfig(); + DOMImplementation getImplementation(); + DocumentFragment createDocumentFragment(); + DocumentType getDoctype(); + Element createElement(String p0); + Element createElementNS(String p0, String p1); + Element getDocumentElement(); + Element getElementById(String p0); + EntityReference createEntityReference(String p0); + Node adoptNode(Node p0); + Node importNode(Node p0, boolean p1); + Node renameNode(Node p0, String p1, String p2); + NodeList getElementsByTagName(String p0); + NodeList getElementsByTagNameNS(String p0, String p1); + ProcessingInstruction createProcessingInstruction(String p0, String p1); + String getDocumentURI(); + String getInputEncoding(); + String getXmlEncoding(); + String getXmlVersion(); + Text createTextNode(String p0); + boolean getStrictErrorChecking(); + boolean getXmlStandalone(); + void normalizeDocument(); + void setDocumentURI(String p0); + void setStrictErrorChecking(boolean p0); + void setXmlStandalone(boolean p0); + void setXmlVersion(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentFragment.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentFragment.java new file mode 100644 index 00000000000..326bfccbf15 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentFragment.java @@ -0,0 +1,9 @@ +// Generated automatically from org.w3c.dom.DocumentFragment for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface DocumentFragment extends Node +{ +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentType.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentType.java new file mode 100644 index 00000000000..18b57c70ab3 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/DocumentType.java @@ -0,0 +1,16 @@ +// Generated automatically from org.w3c.dom.DocumentType for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +public interface DocumentType extends Node +{ + NamedNodeMap getEntities(); + NamedNodeMap getNotations(); + String getInternalSubset(); + String getName(); + String getPublicId(); + String getSystemId(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Element.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Element.java new file mode 100644 index 00000000000..e6e1f9afa21 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Element.java @@ -0,0 +1,32 @@ +// Generated automatically from org.w3c.dom.Element for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.TypeInfo; + +public interface Element extends Node +{ + Attr getAttributeNode(String p0); + Attr getAttributeNodeNS(String p0, String p1); + Attr removeAttributeNode(Attr p0); + Attr setAttributeNode(Attr p0); + Attr setAttributeNodeNS(Attr p0); + NodeList getElementsByTagName(String p0); + NodeList getElementsByTagNameNS(String p0, String p1); + String getAttribute(String p0); + String getAttributeNS(String p0, String p1); + String getTagName(); + TypeInfo getSchemaTypeInfo(); + boolean hasAttribute(String p0); + boolean hasAttributeNS(String p0, String p1); + void removeAttribute(String p0); + void removeAttributeNS(String p0, String p1); + void setAttribute(String p0, String p1); + void setAttributeNS(String p0, String p1, String p2); + void setIdAttribute(String p0, boolean p1); + void setIdAttributeNS(String p0, String p1, boolean p2); + void setIdAttributeNode(Attr p0, boolean p1); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/EntityReference.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/EntityReference.java new file mode 100644 index 00000000000..c4d733c519a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/EntityReference.java @@ -0,0 +1,9 @@ +// Generated automatically from org.w3c.dom.EntityReference for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface EntityReference extends Node +{ +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NamedNodeMap.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NamedNodeMap.java new file mode 100644 index 00000000000..d1f3f1fd5b6 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NamedNodeMap.java @@ -0,0 +1,17 @@ +// Generated automatically from org.w3c.dom.NamedNodeMap for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface NamedNodeMap +{ + Node getNamedItem(String p0); + Node getNamedItemNS(String p0, String p1); + Node item(int p0); + Node removeNamedItem(String p0); + Node removeNamedItemNS(String p0, String p1); + Node setNamedItem(Node p0); + Node setNamedItemNS(Node p0); + int getLength(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Node.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Node.java new file mode 100644 index 00000000000..42dc60a85c9 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Node.java @@ -0,0 +1,67 @@ +// Generated automatically from org.w3c.dom.Node for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.w3c.dom.UserDataHandler; + +public interface Node +{ + Document getOwnerDocument(); + NamedNodeMap getAttributes(); + Node appendChild(Node p0); + Node cloneNode(boolean p0); + Node getFirstChild(); + Node getLastChild(); + Node getNextSibling(); + Node getParentNode(); + Node getPreviousSibling(); + Node insertBefore(Node p0, Node p1); + Node removeChild(Node p0); + Node replaceChild(Node p0, Node p1); + NodeList getChildNodes(); + Object getFeature(String p0, String p1); + Object getUserData(String p0); + Object setUserData(String p0, Object p1, UserDataHandler p2); + String getBaseURI(); + String getLocalName(); + String getNamespaceURI(); + String getNodeName(); + String getNodeValue(); + String getPrefix(); + String getTextContent(); + String lookupNamespaceURI(String p0); + String lookupPrefix(String p0); + boolean hasAttributes(); + boolean hasChildNodes(); + boolean isDefaultNamespace(String p0); + boolean isEqualNode(Node p0); + boolean isSameNode(Node p0); + boolean isSupported(String p0, String p1); + short compareDocumentPosition(Node p0); + short getNodeType(); + static short ATTRIBUTE_NODE = 0; + static short CDATA_SECTION_NODE = 0; + static short COMMENT_NODE = 0; + static short DOCUMENT_FRAGMENT_NODE = 0; + static short DOCUMENT_NODE = 0; + static short DOCUMENT_POSITION_CONTAINED_BY = 0; + static short DOCUMENT_POSITION_CONTAINS = 0; + static short DOCUMENT_POSITION_DISCONNECTED = 0; + static short DOCUMENT_POSITION_FOLLOWING = 0; + static short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0; + static short DOCUMENT_POSITION_PRECEDING = 0; + static short DOCUMENT_TYPE_NODE = 0; + static short ELEMENT_NODE = 0; + static short ENTITY_NODE = 0; + static short ENTITY_REFERENCE_NODE = 0; + static short NOTATION_NODE = 0; + static short PROCESSING_INSTRUCTION_NODE = 0; + static short TEXT_NODE = 0; + void normalize(); + void setNodeValue(String p0); + void setPrefix(String p0); + void setTextContent(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NodeList.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NodeList.java new file mode 100644 index 00000000000..63018fe44ae --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/NodeList.java @@ -0,0 +1,11 @@ +// Generated automatically from org.w3c.dom.NodeList for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface NodeList +{ + Node item(int p0); + int getLength(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/ProcessingInstruction.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/ProcessingInstruction.java new file mode 100644 index 00000000000..57a0ca87b83 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/ProcessingInstruction.java @@ -0,0 +1,12 @@ +// Generated automatically from org.w3c.dom.ProcessingInstruction for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface ProcessingInstruction extends Node +{ + String getData(); + String getTarget(); + void setData(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Text.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Text.java new file mode 100644 index 00000000000..cb715f47e7c --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/Text.java @@ -0,0 +1,13 @@ +// Generated automatically from org.w3c.dom.Text for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.CharacterData; + +public interface Text extends CharacterData +{ + String getWholeText(); + Text replaceWholeText(String p0); + Text splitText(int p0); + boolean isElementContentWhitespace(); +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/TypeInfo.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/TypeInfo.java new file mode 100644 index 00000000000..c62e923a64e --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/TypeInfo.java @@ -0,0 +1,15 @@ +// Generated automatically from org.w3c.dom.TypeInfo for testing purposes + +package org.w3c.dom; + + +public interface TypeInfo +{ + String getTypeName(); + String getTypeNamespace(); + boolean isDerivedFrom(String p0, String p1, int p2); + static int DERIVATION_EXTENSION = 0; + static int DERIVATION_LIST = 0; + static int DERIVATION_RESTRICTION = 0; + static int DERIVATION_UNION = 0; +} diff --git a/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/UserDataHandler.java b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/UserDataHandler.java new file mode 100644 index 00000000000..edf20472b06 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-collections4-4.4/org/w3c/dom/UserDataHandler.java @@ -0,0 +1,15 @@ +// Generated automatically from org.w3c.dom.UserDataHandler for testing purposes + +package org.w3c.dom; + +import org.w3c.dom.Node; + +public interface UserDataHandler +{ + static short NODE_ADOPTED = 0; + static short NODE_CLONED = 0; + static short NODE_DELETED = 0; + static short NODE_IMPORTED = 0; + static short NODE_RENAMED = 0; + void handle(short p0, String p1, Object p2, Node p3, Node p4); +} From b922d7c6f3d0644d6bddbb5d83c639e4c68817a1 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 27 Jul 2021 10:57:28 +0100 Subject: [PATCH 153/429] Duplicate models for old package name The package name was org.apache.commons.collection until release 4.0. --- .../java/frameworks/apache/Collections.qll | 309 +++++++++++++++++- 1 file changed, 296 insertions(+), 13 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 3839ad1d292..782f9cd1ec4 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -127,8 +127,95 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections4;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", "org.apache.commons.collections4;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value", + "org.apache.commons.collections;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections;Bag;true;add;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value", + "org.apache.commons.collections;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", + "org.apache.commons.collections;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", + "org.apache.commons.collections;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", + "org.apache.commons.collections;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", "org.apache.commons.collections;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" + "org.apache.commons.collections;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value", + "org.apache.commons.collections;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value", + "org.apache.commons.collections;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;Put;true;put;;;Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;Put;true;put;;;Argument[1];MapValue of Argument[-1];value", + "org.apache.commons.collections;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + "org.apache.commons.collections;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", + "org.apache.commons.collections;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", + "org.apache.commons.collections;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + "org.apache.commons.collections;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value" ] } } @@ -394,7 +481,44 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value", + "org.apache.commons.collections;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value", + "org.apache.commons.collections;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", + "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", + "org.apache.commons.collections;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", + "org.apache.commons.collections;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" ] } } @@ -431,7 +555,33 @@ private class ApacheListUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;fixedSizeList;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" ] } } @@ -487,7 +637,51 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of Argument[1];Element of Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" ] } } @@ -530,7 +724,38 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" ] } } @@ -544,7 +769,10 @@ private class ApacheEnumerationUtilsModel extends SummaryModelCsv { [ "org.apache.commons.collections4;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections4;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" + "org.apache.commons.collections4;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint", + "org.apache.commons.collections;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" ] } } @@ -564,7 +792,16 @@ private class ApacheMultiMapUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" ] } } @@ -578,7 +815,10 @@ private class ApacheMultiSetUtilsModel extends SummaryModelCsv { [ "org.apache.commons.collections4;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" ] } } @@ -593,7 +833,11 @@ private class ApacheQueueUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" ] } } @@ -629,7 +873,31 @@ private class ApacheSetUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;hashSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" ] } } @@ -644,7 +912,11 @@ private class ApacheSplitMapUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" ] } } @@ -657,7 +929,9 @@ private class ApacheTrieUtilsModel extends SummaryModelCsv { row = [ "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" + "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.collections;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.collections;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" ] } } @@ -677,7 +951,16 @@ private class ApacheBagUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" ] } } From 26f5ac9ff233fb7893895341ad766ff0b32f3143 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 27 Jul 2021 11:03:10 +0100 Subject: [PATCH 154/429] Add change note --- java/change-notes/2021-07-27-apache-collections-base-package.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-07-27-apache-collections-base-package.md diff --git a/java/change-notes/2021-07-27-apache-collections-base-package.md b/java/change-notes/2021-07-27-apache-collections-base-package.md new file mode 100644 index 00000000000..63438d861aa --- /dev/null +++ b/java/change-notes/2021-07-27-apache-collections-base-package.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added models for the base package of Apache Commons Collections. This may lead to more results from any query using data-flow analysis where a relevant path uses one of these container types. From d1a440a45aea9162f15fb75d2a79fa06680417fe Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 4 Aug 2021 13:57:38 +0100 Subject: [PATCH 155/429] Improve helper functions for Put --- .../library-tests/frameworks/apache-collections/Test.java | 4 ++-- .../test/library-tests/frameworks/apache-collections/test.ql | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 20606fa9a71..75515126006 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -91,14 +91,14 @@ public class Test { static Object getMapKey(AbstractMapEntryDecorator container) { return container.getKey(); } static Object getMapKey(Map container) { return container.keySet().iterator().next(); } static Object getMapKey(MultiValuedMap container) { return container.keySet().iterator().next(); } - static Object getMapKeyFromPut(Put container) { return null; } + static Object getMapKeyFromPut(Put container) { return getMapKey((Map)container); } static Object getMapValue(AbstractKeyValue container) { return container.getValue(); } static Object getMapValueFromEntry(Map.Entry container) { return container.getValue(); } static Object getMapValue(AbstractMapEntryDecorator container) { return container.getValue(); } static Object getMapValue(Map container) { return container.get(null); } static Object getMapValue(MapIterator container) { return container.getValue(); } static Collection getMapValue(MultiValuedMap container) { return container.get(null); } - static Object getMapValueFromPut(Put container) { return null; } + static Object getMapValueFromPut(Put container) { return getMapValue((Map)container); } Object[] newWithArrayElement(Object element) { return new Object[] {element}; } ArrayStack newArrayStackWithElement(String element) { ArrayStack a = new ArrayStack(); a.push(element); return a; } diff --git a/java/ql/test/library-tests/frameworks/apache-collections/test.ql b/java/ql/test/library-tests/frameworks/apache-collections/test.ql index 76541c1843d..74a65d5922e 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/test.ql +++ b/java/ql/test/library-tests/frameworks/apache-collections/test.ql @@ -10,8 +10,6 @@ class SummaryModelTest extends SummaryModelCsv { [ //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", "org.apache.commons.collections4.iterators;IteratorEnumeration;true;IteratorEnumeration;;;Element of Argument[0];Element of Argument[-1];value", - "generatedtest;Test;false;getMapKeyFromPut;;;MapKey of Argument[0];ReturnValue;value", - "generatedtest;Test;false;getMapValueFromPut;;;MapValue of Argument[0];ReturnValue;value", "generatedtest;Test;false;newRBWithMapValue;;;Argument[0];MapValue of ReturnValue;value", "generatedtest;Test;false;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value" ] From 2ba41df2baaac6543a8049b6af98863a40aae982 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 4 Aug 2021 13:58:31 +0100 Subject: [PATCH 156/429] Remove commented line --- .../test/library-tests/frameworks/apache-collections/Test.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 75515126006..6f6482aeaba 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -120,7 +120,6 @@ public class Test { HashedMap newHashedMapWithMapKey(Object element) { HashedMap m = new HashedMap(); m.put(element,null); return m; } MyAbstractMapEntry newMAMEWithMapKey(Object element) { return new MyAbstractMapEntry(element,null); } MyAbstractMapEntryDecorator newMAMEDWithMapKey(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapKey(element)); } - // MultiMap newMMWithMapKey(Object element) { MultiMap m = new MultiValueMap(); m.put(element,null); return m; } MultiValuedMap newMVMWithMapKey(Object element) { MultiValuedMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } OrderedMapIterator newOMIWithElement(Object element) { LinkedMap m = new LinkedMap(); m.put(element,null); return m.mapIterator(); } ResourceBundle newRBWithMapKey(Object element) { return (ResourceBundle)null; } From 9533f12e2427357f5ad2fffa3956caafbc4b2415 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 4 Aug 2021 14:01:00 +0100 Subject: [PATCH 157/429] Add explanatory commented for MapIterator model --- java/ql/src/semmle/code/java/frameworks/apache/Collections.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 782f9cd1ec4..2cd0c7d2445 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -84,6 +84,8 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + // Note that MapIterator implements Iterator, so it iterates over the keys of the map. + // In order for the models of Iterator to work we have to use Element instead of MapKey for key data. "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value", From df0f9ee3a552e283eb5538f3cc82cf618d9bdb30 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Sun, 8 Aug 2021 12:50:04 +0200 Subject: [PATCH 158/429] Fixed a few typos --- .../Security/CWE/CWE-1204/StaticInitializationVector.qhelp | 2 +- .../Security/CWE/CWE-1204/StaticInitializationVector.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp index 49f5862f3de..d631dff22af 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.qhelp @@ -6,7 +6,7 @@ A cipher needs an initialization vector (IV) when it is used in certain modes such as CBC or GCM. Under the same secret key, IVs should be unique and ideally unpredictable. Given a secret key, if the same IV is used for encryption, the same plaintexts result in the same ciphertexts. -This lets an attacker learn if the same data pieces are transfered or stored, +This lets an attacker learn if the same data pieces are transferred or stored, or this can help the attacker run a dictionary attack.

    diff --git a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql index f041919ed93..9980f68ed80 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-1204/StaticInitializationVector.ql @@ -5,7 +5,7 @@ * therefore they should be unique and ideally unpredictable. * Otherwise, the same plaintexts result in same ciphertexts under a given secret key. * If a static IV is used for encryption, this lets an attacker learn - * if the same data pieces are transfered or stored, + * if the same data pieces are transferred or stored, * or this can help the attacker run a dictionary attack. * @kind path-problem * @problem.severity warning From 5d3f10824e070c50ea197214b2e75c839ed11de9 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 4 Aug 2021 14:44:28 +0100 Subject: [PATCH 159/429] Fix erroneous treatment of varargs in models --- .../java/frameworks/apache/Collections.qll | 18 +++++----- .../frameworks/apache-collections/Test.java | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 2cd0c7d2445..54e8979bbb5 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -607,7 +607,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of Argument[1];Element of Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", @@ -634,7 +634,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", @@ -651,7 +651,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of Argument[1];Element of Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", @@ -678,7 +678,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", @@ -697,7 +697,7 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { [ // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterable "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", @@ -725,10 +725,10 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable[]);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", @@ -756,7 +756,7 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" ] } @@ -858,7 +858,7 @@ private class ApacheSetUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;hashSet;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;hashSet;;;ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 6f6482aeaba..59d6327c4ca 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -1863,6 +1863,13 @@ public class Test { out = IterableUtils.boundedIterable(in, 0L); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value" + Iterable out = null; + Iterable in = newVectorWithElement((String)source()); + out = IterableUtils.chainedIterable(in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; @@ -2080,6 +2087,13 @@ public class Test { out = IterableUtils.zippingIterable((Iterable)null, in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value" + Iterable out = null; + Iterable in = newVectorWithElement((String)source()); + out = IterableUtils.zippingIterable((Iterable)null, in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; @@ -2213,6 +2227,13 @@ public class Test { out = IteratorUtils.collatedIterator((Comparator)null, in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value" + Iterator out = null; + Iterator in = newListIteratorWithElement((String)source()); + out = IteratorUtils.collatedIterator((Comparator)null, in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value" Iterator out = null; @@ -2416,6 +2437,13 @@ public class Test { out = IteratorUtils.unmodifiableMapIterator(in); sink(getMapValue(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value" + ZippingIterator out = null; + Iterator in = newListIteratorWithElement((String)source()); + out = IteratorUtils.zippingIterator(in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" ZippingIterator out = null; @@ -3123,6 +3151,13 @@ public class Test { out = SetUtils.emptyIfNull(in); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;SetUtils;true;hashSet;;;ArrayElement of Argument[0];Element of ReturnValue;value" + HashSet out = null; + Object in = source(); + out = SetUtils.hashSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; From 377403d52534989596bf594df8be239cfdcef761 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 4 Aug 2021 15:57:13 +0100 Subject: [PATCH 160/429] Remove redundant models and corresponding test Iterator.next is already modelled --- .../src/semmle/code/java/frameworks/apache/Collections.qll | 2 -- .../library-tests/frameworks/apache-collections/Test.java | 7 ------- 2 files changed, 9 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 54e8979bbb5..7ce2fa0721f 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -88,7 +88,6 @@ private class ApacheCollectionsModel extends SummaryModelCsv { // In order for the models of Iterator to work we have to use Element instead of MapKey for key data. "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", "org.apache.commons.collections4;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", @@ -177,7 +176,6 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", "org.apache.commons.collections;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", "org.apache.commons.collections;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", "org.apache.commons.collections;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 59d6327c4ca..b5cbd450994 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -2675,13 +2675,6 @@ public class Test { out = in.getValue(); sink(out); // $ hasValueFlow } - { - // "org.apache.commons.collections4;MapIterator;true;next;;;Element of Argument[-1];ReturnValue;value" - Object out = null; - MapIterator in = newOMIWithElement((String)source()); - out = in.next(); - sink(out); // $ hasValueFlow - } { // "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value" MapIterator out = null; From f94e467076735d61a3a916c68916bb803beb3ba6 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 30 Jun 2021 15:17:02 +0100 Subject: [PATCH 161/429] Fixes to models and tests Running the test generator script again showed many missing tests. --- .../java/frameworks/apache/Collections.qll | 46 +- .../frameworks/apache-collections/Test.java | 426 +++++++++++++++++- 2 files changed, 436 insertions(+), 36 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 7ce2fa0721f..3f6e0de99ab 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -72,7 +72,7 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections4;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", @@ -113,6 +113,7 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections4;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections4;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", @@ -162,7 +163,7 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + "org.apache.commons.collections;FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", "org.apache.commons.collections;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", @@ -201,6 +202,7 @@ private class ApacheCollectionsModel extends SummaryModelCsv { "org.apache.commons.collections;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", + "org.apache.commons.collections;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", "org.apache.commons.collections;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", @@ -458,6 +460,7 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections4;CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", @@ -495,6 +498,7 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", + "org.apache.commons.collections;CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value", "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", @@ -530,9 +534,10 @@ private class ApacheListUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = [ + "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", @@ -556,9 +561,10 @@ private class ApacheListUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value", "org.apache.commons.collections;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", "org.apache.commons.collections;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;fixedSizeList;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", @@ -602,6 +608,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", @@ -625,9 +632,12 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", + "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", + "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", @@ -646,6 +656,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", @@ -669,9 +680,12 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", + "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", + "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", "org.apache.commons.collections;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", @@ -720,6 +734,9 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", + "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", + "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", @@ -751,6 +768,9 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { "org.apache.commons.collections;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", + "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", + "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", "org.apache.commons.collections;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", @@ -852,9 +872,10 @@ private class ApacheSetUtilsModel extends SummaryModelCsv { [ "org.apache.commons.collections4;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", "org.apache.commons.collections4;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections4;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;hashSet;;;ArrayElement of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", @@ -876,9 +897,10 @@ private class ApacheSetUtilsModel extends SummaryModelCsv { "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", "org.apache.commons.collections;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of Argument[0];value", + "org.apache.commons.collections;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value", "org.apache.commons.collections;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + "org.apache.commons.collections;SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", "org.apache.commons.collections;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", "org.apache.commons.collections;SetUtils;true;hashSet;;;Element of Argument[0];Element of ReturnValue;value", "org.apache.commons.collections;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index b5cbd450994..00f62a125e1 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -3,6 +3,7 @@ package generatedtest; import java.util.Collection; import java.util.Comparator; import java.util.Enumeration; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -70,6 +71,8 @@ import org.apache.commons.collections4.keyvalue.DefaultKeyValue; import org.apache.commons.collections4.keyvalue.DefaultMapEntry; import org.apache.commons.collections4.keyvalue.TiedMapEntry; import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry; +import org.apache.commons.collections4.map.AbstractIterableMap; +import org.apache.commons.collections4.map.AbstractMapDecorator; import org.apache.commons.collections4.map.HashedMap; import org.apache.commons.collections4.map.LinkedMap; import org.apache.commons.collections4.map.MultiValueMap; @@ -120,7 +123,8 @@ public class Test { HashedMap newHashedMapWithMapKey(Object element) { HashedMap m = new HashedMap(); m.put(element,null); return m; } MyAbstractMapEntry newMAMEWithMapKey(Object element) { return new MyAbstractMapEntry(element,null); } MyAbstractMapEntryDecorator newMAMEDWithMapKey(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapKey(element)); } - MultiValuedMap newMVMWithMapKey(Object element) { MultiValuedMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } + MultiValueMap newMVMWithMapKey(Object element) { MultiValueMap m = new MultiValueMap(); m.put(element,null); return m; } + MultiValuedMap newMVdMWithMapKey(Object element) { MultiValuedMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } OrderedMapIterator newOMIWithElement(Object element) { LinkedMap m = new LinkedMap(); m.put(element,null); return m.mapIterator(); } ResourceBundle newRBWithMapKey(Object element) { return (ResourceBundle)null; } SortedMap newTreeMapWithMapKey(Object element) { SortedMap m = new TreeMap(); m.put(element,null); return m; } @@ -133,6 +137,7 @@ public class Test { HashedMap newHashedMapWithMapValue(Object element) { HashedMap m = new HashedMap(); m.put(null,element); return m; } MyAbstractMapEntry newMAMEWithMapValue(Object element) { return new MyAbstractMapEntry(null,element); } MyAbstractMapEntryDecorator newMAMEDWithMapValue(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapValue(element)); } + MultiValueMap newMVMWithMapValue(Object element) { MultiValueMap m = new MultiValueMap(); m.put(null,element); return m; } MultiMap newMMWithMapValue(Object element) { MultiMap m = new MultiValueMap(); m.put(null,element); return m; } ArrayListValuedHashMap newALVHMWithMapValue(Object element) { ArrayListValuedHashMap m = new ArrayListValuedHashMap(); m.put(null,element); return m; } HashSetValuedHashMap newHSVHMWithMapValue(Object element) { HashSetValuedHashMap m = new HashSetValuedHashMap(); m.put(null,element); return m; } @@ -307,7 +312,7 @@ public class Test { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); - out = in.mySetValue(null); + out = in.mySetValue((Object)null); sink(out); // $ hasValueFlow } { @@ -1355,6 +1360,13 @@ public class Test { out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = newVectorWithElement((String)source()); + out = CollectionUtils.get(in, 0); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value" Map.Entry out = null; @@ -1608,6 +1620,14 @@ public class Test { out = instance.append(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Object in = source(); + FluentIterable instance = null; + out = instance.append(in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; @@ -1729,6 +1749,13 @@ public class Test { out = in.skip(0L); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value" + Object[] out = null; + FluentIterable in = newFluentIterableWithElement((String)source()); + out = in.toArray(null); + sink(getArrayElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value" List out = null; @@ -1772,6 +1799,28 @@ public class Test { out = instance.zip(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value" + FluentIterable out = null; + FluentIterable in = newFluentIterableWithElement((String)source()); + out = in.zip((Iterable)null, (Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value" + FluentIterable out = null; + Iterable in = newVectorWithElement((String)source()); + FluentIterable instance = null; + out = instance.zip(in, (Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" + Set out = null; + MultiValueMap in = newMVMWithMapKey((String)source()); + out = in.entrySet(); + sink(getMapKeyFromEntry(getElement(out))); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" Set out = null; @@ -1779,6 +1828,20 @@ public class Test { out = in.entrySet(); sink(getMapKeyFromEntry(getElement(out))); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" + Set out = null; + AbstractMapDecorator in = newMVMWithMapKey((String)source()); + out = in.entrySet(); + sink(getMapKeyFromEntry(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value" + Set out = null; + MultiValueMap in = newMVMWithMapValue((String)source()); + out = in.entrySet(); + sink(getMapValueFromEntry(getElement(out))); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value" Set out = null; @@ -1786,6 +1849,13 @@ public class Test { out = in.entrySet(); sink(getMapValueFromEntry(getElement(out))); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value" + Set out = null; + AbstractMapDecorator in = newMVMWithMapValue((String)source()); + out = in.entrySet(); + sink(getMapValueFromEntry(getElement(out))); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; @@ -1800,6 +1870,13 @@ public class Test { out = in.get(null); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + AbstractMapDecorator in = newMVMWithMapValue((String)source()); + out = in.get(null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; @@ -1807,6 +1884,13 @@ public class Test { out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value" + Set out = null; + AbstractMapDecorator in = newMVMWithMapKey((String)source()); + out = in.keySet(); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" Object out = null; @@ -1821,6 +1905,13 @@ public class Test { out = in.remove(null); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + AbstractMapDecorator in = newMVMWithMapValue((String)source()); + out = in.remove(null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" Set out = null; @@ -1828,6 +1919,13 @@ public class Test { out = in.values(); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiValueMap in = newMVMWithMapValue((String)source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; @@ -1842,6 +1940,20 @@ public class Test { out = in.values(); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + AbstractMapDecorator in = newMVMWithMapValue((String)source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" + OrderedMapIterator out = null; + OrderedMap in = newTreeBidiMapWithMapKey((String)source()); + out = in.mapIterator(); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" MapIterator out = null; @@ -1849,6 +1961,20 @@ public class Test { out = in.mapIterator(); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" + MapIterator out = null; + AbstractIterableMap in = newMVMWithMapKey((String)source()); + out = in.mapIterator(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value" + OrderedMapIterator out = null; + OrderedMap in = newTreeBidiMapWithMapValue((String)source()); + out = in.mapIterator(); + sink(getMapValue(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value" MapIterator out = null; @@ -1856,6 +1982,13 @@ public class Test { out = in.mapIterator(); sink(getMapValue(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value" + MapIterator out = null; + AbstractIterableMap in = newMVMWithMapValue((String)source()); + out = in.mapIterator(); + sink(getMapValue(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; @@ -1867,7 +2000,7 @@ public class Test { // "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value" Iterable out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.chainedIterable(in); + out = IterableUtils.chainedIterable(in, (Iterable)null); sink(getElement(out)); // $ hasValueFlow } { @@ -2007,21 +2140,21 @@ public class Test { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.partition(in, null, (Predicate[])null); + out = IterableUtils.partition(in, (Factory)null, (Predicate)null, (Predicate)null); sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.partition(in, (Predicate[])null); + out = IterableUtils.partition(in, (Predicate)null, (Predicate)null); sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.partition(in, (Predicate)null); + out = IterableUtils.partition(in, (Predicate)null, (Predicate)null); sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { @@ -2066,6 +2199,27 @@ public class Test { out = IterableUtils.toString(in); sink(out); // $ hasTaintFlow } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IterableUtils.toString(null, null, in, null, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[3];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IterableUtils.toString(null, null, null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[4];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IterableUtils.toString(null, null, null, null, in); + sink(out); // $ hasTaintFlow + } { // "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; @@ -2098,14 +2252,35 @@ public class Test { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.zippingIterable(in, (Iterable)null); + out = IterableUtils.zippingIterable(in, (Iterable)null, (Iterable)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value" Iterable out = null; Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.zippingIterable(in); + out = IterableUtils.zippingIterable(in, (Iterable)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object[] in = newWithArrayElement((String)source()); + out = IteratorUtils.arrayIterator(in, 0, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object[] in = newWithArrayElement((String)source()); + out = IteratorUtils.arrayIterator(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableIterator out = null; + Object in = source(); + out = IteratorUtils.arrayIterator(in, (Object)null); sink(getElement(out)); // $ hasValueFlow } { @@ -2129,6 +2304,27 @@ public class Test { out = IteratorUtils.arrayIterator(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object[] in = newWithArrayElement((String)source()); + out = IteratorUtils.arrayListIterator(in, 0, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object[] in = newWithArrayElement((String)source()); + out = IteratorUtils.arrayListIterator(in, 0); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" + ResettableListIterator out = null; + Object in = source(); + out = IteratorUtils.arrayListIterator(in, (Object)null); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; @@ -2206,6 +2402,13 @@ public class Test { out = IteratorUtils.chainedIterator(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value" + Iterator out = null; + Iterator in = newListIteratorWithElement((String)source()); + out = IteratorUtils.chainedIterator(in, (Iterator)null); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; @@ -2360,6 +2563,13 @@ public class Test { out = IteratorUtils.skippingIterator(in, 0L); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value" + Object[] out = null; + Iterator in = newListIteratorWithElement((String)source()); + out = IteratorUtils.toArray(in, null); + sink(getArrayElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value" Object[] out = null; @@ -2368,23 +2578,23 @@ public class Test { sink(getArrayElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value" + // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterator in = (Iterator)source(); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toList(in, 0); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Argument[0];Element of ReturnValue;value" + // "org.apache.commons.collections4;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Iterator in = (Iterator)source(); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toList(in); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Argument[0];Element of ReturnValue;value" + // "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value" ListIterator out = null; - Iterator in = (Iterator)source(); + Iterator in = newListIteratorWithElement((String)source()); out = IteratorUtils.toListIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2409,6 +2619,27 @@ public class Test { out = IteratorUtils.toString(in); sink(out); // $ hasTaintFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IteratorUtils.toString(null, null, in, null, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IteratorUtils.toString(null, null, null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = IteratorUtils.toString(null, null, null, null, in); + sink(out); // $ hasTaintFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; @@ -2428,7 +2659,7 @@ public class Test { MapIterator out = null; MapIterator in = newOMIWithElement((String)source()); out = IteratorUtils.unmodifiableMapIterator(in); - sink(getElement((Iterator)out)); // $ hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value" @@ -2479,6 +2710,13 @@ public class Test { out = IteratorUtils.zippingIterator(null, null, in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value" + List out = null; + List in = (List)source(); + out = ListUtils.defaultIfNull(in, null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value" List out = null; @@ -2493,6 +2731,13 @@ public class Test { out = ListUtils.emptyIfNull(in); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value" + List out = null; + List in = (List)newVectorWithElement((String)source()); + out = ListUtils.fixedSizeList(in); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" List out = null; @@ -2696,6 +2941,13 @@ public class Test { out = (Collection)in.get(null); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value" + MultiValueMap out = null; + Object in = source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value" MultiMap out = null; @@ -2703,6 +2955,13 @@ public class Test { out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" + MultiValueMap out = null; + Object in = source(); + out.put(null, in); + sink(getElement((Collection)getMapValue(out))); // $ hasValueFlow + } { // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" MultiMap out = null; @@ -2710,6 +2969,13 @@ public class Test { out.put(null, in); sink(getElement((Collection)getMapValue(out))); // $ hasValueFlow } + { + // "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiValueMap in = newMVMWithMapValue((String)source()); + out = in.values(); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; @@ -2755,7 +3021,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = MultiMapUtils.transformedMultiValuedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } @@ -2769,7 +3035,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = MultiMapUtils.unmodifiableMultiValuedMap(in); sink(getMapKey(out)); // $ hasValueFlow } @@ -2846,7 +3112,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = in.asMap(); sink(getMapKey(out)); // $ hasValueFlow } @@ -2874,14 +3140,14 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value" MultiSet out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = in.keys(); sink(getElement(out)); // $ hasValueFlow } @@ -2895,7 +3161,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" MapIterator out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out = in.mapIterator(); sink(getElement(out)); // $ hasValueFlow } @@ -2937,7 +3203,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - MultiValuedMap in = newMVMWithMapKey((String)source()); + MultiValuedMap in = newMVdMWithMapKey((String)source()); out.putAll(in); sink(getMapKey(out)); // $ hasValueFlow } @@ -2955,6 +3221,27 @@ public class Test { out.putAll(null, in); sink(getElement(getMapValue(out))); // $ hasValueFlow } + { + // "org.apache.commons.collections4;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Set out = null; + SetValuedMap in = newHSVHMWithMapValue((String)source()); + out = in.remove(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + List out = null; + ListValuedMap in = newALVHMWithMapValue((String)source()); + out = in.remove(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" + Collection out = null; + MultiValuedMap in = newALVHMWithMapValue((String)source()); + out = in.remove(null); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value" Collection out = null; @@ -3011,6 +3298,13 @@ public class Test { out.put(in, null); sink(getMapKeyFromPut(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" + MultiValueMap out = null; + Object in = source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" MultiMap out = null; @@ -3025,6 +3319,13 @@ public class Test { out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" + AbstractMapDecorator out = null; + Object in = source(); + out.put(in, null); + sink(getMapKey(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" Put out = null; @@ -3032,6 +3333,13 @@ public class Test { out.put(null, in); sink(getMapValueFromPut(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" + MultiValueMap out = null; + Object in = source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" MultiMap out = null; @@ -3046,6 +3354,13 @@ public class Test { out.put(null, in); sink(getMapValue(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" + AbstractMapDecorator out = null; + Object in = source(); + out.put(null, in); + sink(getMapValue(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; @@ -3053,6 +3368,13 @@ public class Test { out = in.put(null, null); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + MultiValueMap in = newMVMWithMapValue((String)source()); + out = in.put(null, null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" Object out = null; @@ -3067,6 +3389,13 @@ public class Test { out = in.put(null, null); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + AbstractMapDecorator in = newMVMWithMapValue((String)source()); + out = in.put(null, null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" Put out = null; @@ -3074,6 +3403,20 @@ public class Test { out.putAll(in); sink(getMapKeyFromPut(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" + MultiValueMap out = null; + Map in = newTreeMapWithMapKey((String)source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value" + AbstractMapDecorator out = null; + Map in = newTreeMapWithMapKey((String)source()); + out.putAll(in); + sink(getMapKey(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" Put out = null; @@ -3081,6 +3424,20 @@ public class Test { out.putAll(in); sink(getMapValueFromPut(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" + MultiValueMap out = null; + Map in = newTreeMapWithMapValue((String)source()); + out.putAll(in); + sink(getMapValue(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value" + AbstractMapDecorator out = null; + Map in = newTreeMapWithMapValue((String)source()); + out.putAll(in); + sink(getMapValue(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value" Queue out = null; @@ -3123,6 +3480,13 @@ public class Test { out = in.myCreateIterator(); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value" + Set out = null; + MySetView in = newSetViewWithElement((String)source()); + out = in.toSet(); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; @@ -3131,10 +3495,17 @@ public class Test { sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[1];Element of ReturnValue;value" + // "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value" SetUtils.SetView out = null; Set in = newTreeSetWithElement((String)source()); - out = SetUtils.difference(null, in); + out = SetUtils.disjunction(in, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value" + SetUtils.SetView out = null; + Set in = newTreeSetWithElement((String)source()); + out = SetUtils.disjunction(null, in); sink(getElement(out)); // $ hasValueFlow } { @@ -3249,6 +3620,13 @@ public class Test { out = SetUtils.unmodifiableNavigableSet(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" + Set out = null; + Object in = source(); + out = SetUtils.unmodifiableSet(in, null); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value" Set out = null; From 1997dfbb4ae3c4d17a6a6f259d44e23abfa86c7c Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 6 Aug 2021 07:13:57 +0100 Subject: [PATCH 162/429] Remove unnecessary casts --- .../frameworks/apache-collections/Test.java | 150 +++++++++--------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 00f62a125e1..568823a73a4 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -1111,21 +1111,21 @@ public class Test { { // "org.apache.commons.collections4;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value" ArrayStack out = null; - Object in = (Object)source(); + Object in = source(); out.push(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value" Bag out = null; - Object in = (Object)source(); + Object in = source(); out.add(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value" Bag out = null; - Object in = (Object)source(); + Object in = source(); out.add(in); sink(getElement(out)); // $ hasValueFlow } @@ -1146,7 +1146,7 @@ public class Test { { // "org.apache.commons.collections4;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value" Bag out = null; - Bag in = (Bag)newTreeBagWithElement((String)source()); + Bag in = newTreeBagWithElement((String)source()); out = BagUtils.predicatedBag(in, null); sink(getElement(out)); // $ hasValueFlow } @@ -1251,14 +1251,14 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value" Collection out = null; - String[] in = (String[])newWithArrayElement((String)source()); + Object[] in = newWithArrayElement((String)source()); CollectionUtils.addAll(out, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value" Collection out = null; - Object in = (Object)source(); + Object in = source(); CollectionUtils.addIgnoreNull(out, in); sink(getElement(out)); // $ hasValueFlow } @@ -1342,7 +1342,7 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value" Object out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.extractSingleton(in); sink(out); // $ hasValueFlow } @@ -1370,42 +1370,42 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value" Map.Entry out = null; - Map in = (Map)newTreeMapWithMapKey((String)source()); + Map in = newTreeMapWithMapKey((String)source()); out = CollectionUtils.get(in, 0); sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value" Map.Entry out = null; - Map in = (Map)newTreeMapWithMapValue((String)source()); + Map in = newTreeMapWithMapValue((String)source()); out = CollectionUtils.get(in, 0); sink(getMapValueFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value" Object out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value" Object out = null; - Object in = (Object)newVectorWithElement((String)source()); + Object in = newVectorWithElement((String)source()); out = CollectionUtils.get(in, 0); sink(out); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value" Map.Entry out = null; - Object in = (Object)newTreeMapWithMapKey((String)source()); + Object in = newTreeMapWithMapKey((String)source()); out = (Map.Entry)CollectionUtils.get(in, 0); sink(getMapKeyFromEntry(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value" Map.Entry out = null; - Object in = (Object)newTreeMapWithMapValue((String)source()); + Object in = newTreeMapWithMapValue((String)source()); out = (Map.Entry)CollectionUtils.get(in, 0); sink(getMapValueFromEntry(out)); // $ hasValueFlow } @@ -1433,14 +1433,14 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.permutations(in); sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.predicatedCollection(in, null); sink(getElement(out)); // $ hasValueFlow } @@ -1454,7 +1454,7 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.removeAll(in, null); sink(getElement(out)); // $ hasValueFlow } @@ -1468,7 +1468,7 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.retainAll(in, null); sink(getElement(out)); // $ hasValueFlow } @@ -1552,14 +1552,14 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.synchronizedCollection(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.transformingCollection(in, null); sink(getElement(out)); // $ hasValueFlow } @@ -1580,7 +1580,7 @@ public class Test { { // "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = CollectionUtils.unmodifiableCollection(in); sink(getElement(out)); // $ hasValueFlow } @@ -1724,14 +1724,14 @@ public class Test { { // "org.apache.commons.collections4;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value" FluentIterable out = null; - Object in = (Object)source(); + Object in = source(); out = FluentIterable.of(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value" FluentIterable out = null; - String[] in = (String[])newWithArrayElement((String)source()); + Object[] in = newWithArrayElement((String)source()); out = FluentIterable.of(in); sink(getElement(out)); // $ hasValueFlow } @@ -2286,21 +2286,21 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in, 0, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2328,21 +2328,21 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in, 0, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.arrayListIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2398,7 +2398,7 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Collection in = (Collection)newVectorWithElement(newVectorWithElement((String)source())); + Collection in = newVectorWithElement(newVectorWithElement((String)source())); out = IteratorUtils.chainedIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2426,7 +2426,7 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value" Iterator out = null; - Collection in = (Collection)newVectorWithElement(newVectorWithElement((String)source())); + Collection in = newVectorWithElement(newVectorWithElement((String)source())); out = IteratorUtils.collatedIterator((Comparator)null, in); sink(getElement(out)); // $ hasValueFlow } @@ -2489,42 +2489,42 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)source(); + Object in = source(); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)newWithArrayElement((String)source()); + Object in = newWithArrayElement((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value" Iterator out = null; - Object in = (Object)newVectorWithElement((String)source()); + Object in = newVectorWithElement((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value" Iterator out = null; - Map in = (Map)newTreeMapWithMapValue((String)source()); + Map in = newTreeMapWithMapValue((String)source()); out = IteratorUtils.getIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = IteratorUtils.loopingIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value" ResettableListIterator out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = IteratorUtils.loopingListIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2545,14 +2545,14 @@ public class Test { { // "org.apache.commons.collections4;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value" ResettableIterator out = null; - Object in = (Object)source(); + Object in = source(); out = IteratorUtils.singletonIterator(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value" ListIterator out = null; - Object in = (Object)source(); + Object in = source(); out = IteratorUtils.singletonListIterator(in); sink(getElement(out)); // $ hasValueFlow } @@ -2734,35 +2734,35 @@ public class Test { { // "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.fixedSizeList(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.intersection(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.intersection(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.lazyList(in, (Transformer)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.lazyList(in, (Factory)null); sink(getElement(out)); // $ hasValueFlow } @@ -2783,126 +2783,126 @@ public class Test { { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(in, (List)null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence((List)null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(in, null, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.longestCommonSubsequence(null, in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.partition(in, 0); sink(getElement((Iterable)getElement(out))); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.predicatedList(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = ListUtils.removeAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = ListUtils.retainAll(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = ListUtils.select(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - Collection in = (Collection)newVectorWithElement((String)source()); + Collection in = newVectorWithElement((String)source()); out = ListUtils.selectRejected(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.subtract(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.sum(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.sum(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.synchronizedList(in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.transformedList(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.union(in, null); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.union(null, in); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" List out = null; - List in = (List)newVectorWithElement((String)source()); + List in = newVectorWithElement((String)source()); out = ListUtils.unmodifiableList(in); sink(getElement(out)); // $ hasValueFlow } @@ -2923,7 +2923,7 @@ public class Test { { // "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value" MapIterator out = null; - Object in = (Object)source(); + Object in = source(); out.setValue(in); sink(getMapValue(out)); // $ hasValueFlow } @@ -2951,7 +2951,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value" MultiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } @@ -2965,7 +2965,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" MultiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getElement((Collection)getMapValue(out))); // $ hasValueFlow } @@ -3056,14 +3056,14 @@ public class Test { { // "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value" MultiSet out = null; - Object in = (Object)source(); + Object in = source(); out.add(in, 0); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value" MultiSet out = null; - Object in = (Object)source(); + Object in = source(); out.add(in); sink(getElement(out)); // $ hasValueFlow } @@ -3168,14 +3168,14 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value" MultiValuedMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getElement(getMapValue(out))); // $ hasValueFlow } @@ -3210,7 +3210,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - Object in = (Object)source(); + Object in = source(); out.putAll(in, null); sink(getMapKey(out)); // $ hasValueFlow } @@ -3294,7 +3294,7 @@ public class Test { { // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" Put out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKeyFromPut(out)); // $ hasValueFlow } @@ -3308,14 +3308,14 @@ public class Test { { // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" MultiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value" BidiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(in, null); sink(getMapKey(out)); // $ hasValueFlow } @@ -3329,7 +3329,7 @@ public class Test { { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" Put out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getMapValueFromPut(out)); // $ hasValueFlow } @@ -3343,14 +3343,14 @@ public class Test { { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" MultiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getMapValue(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value" BidiMap out = null; - Object in = (Object)source(); + Object in = source(); out.put(null, in); sink(getMapValue(out)); // $ hasValueFlow } From 91bd3d1a11239495c6cbc1231957d128861a8435 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 9 Aug 2021 10:28:31 +0200 Subject: [PATCH 163/429] Cache getName to improve performance --- csharp/ql/src/semmle/code/dotnet/Element.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/src/semmle/code/dotnet/Element.qll b/csharp/ql/src/semmle/code/dotnet/Element.qll index 1f23c43215d..0138766cc58 100644 --- a/csharp/ql/src/semmle/code/dotnet/Element.qll +++ b/csharp/ql/src/semmle/code/dotnet/Element.qll @@ -57,6 +57,7 @@ class Element extends @dotnet_element { /** An element that has a name. */ class NamedElement extends Element, @dotnet_named_element { /** Gets the name of this element. */ + cached string getName() { none() } /** Holds if this element has name 'name'. */ From 021e40529425981ec2f8e11158fb02e3f0b27e42 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 9 Aug 2021 15:33:21 +0100 Subject: [PATCH 164/429] Elaborate change note a little --- .../2021-06-22-more-steps-for-bytebuffer-inputstream.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/change-notes/2021-06-22-more-steps-for-bytebuffer-inputstream.md b/java/change-notes/2021-06-22-more-steps-for-bytebuffer-inputstream.md index 8ffaf6926ea..a3528dfd6f1 100644 --- a/java/change-notes/2021-06-22-more-steps-for-bytebuffer-inputstream.md +++ b/java/change-notes/2021-06-22-more-steps-for-bytebuffer-inputstream.md @@ -1,2 +1,2 @@ lgtm,codescanning -* Added more taint propagation steps for `InputStream` and `ByteBuffer`. +* Added more taint propagation models of some `java.io.InputStream` and `java.nio.ByteBuffer` methods. This may lead to extra results from queries concerning data-flow whenever a relevant path involves an instance of one of those types. From 487a46ae77d2b19a07da322691719b50a8776fc5 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 9 Aug 2021 14:27:53 +0100 Subject: [PATCH 165/429] Improve treatment of new and old package name --- .../java/frameworks/apache/Collections.qll | 1265 ++++++----------- 1 file changed, 444 insertions(+), 821 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 3f6e0de99ab..0b308406b1c 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -36,189 +36,101 @@ class MethodApacheCollectionsIsNotEmpty extends Method { private class ApacheCollectionsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - // Note that when lambdas are supported we should model things relating to Closure, Factory, Transformer, FluentIterable.forEach, FluentIterable.transform - "org.apache.commons.collections4;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections4;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", - "org.apache.commons.collections4;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections4;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", - "org.apache.commons.collections4;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", - "org.apache.commons.collections4;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - // Note that MapIterator implements Iterator, so it iterates over the keys of the map. - // In order for the models of Iterator to work we have to use Element instead of MapKey for key data. - "org.apache.commons.collections4;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections4;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections4;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;Put;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;Put;true;put;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections;ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections;Bag;true;add;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections;Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections;BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", - "org.apache.commons.collections;FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", - "org.apache.commons.collections;Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", - "org.apache.commons.collections;Get;true;get;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections;KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;MultiSet;true;add;;;Argument[0];Element of Argument[-1];value", - "org.apache.commons.collections;MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", - "org.apache.commons.collections;MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;Put;true;put;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;Put;true;put;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;Put;true;put;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections;Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections;Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections;SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", - "org.apache.commons.collections;Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections;Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + // Note that when lambdas are supported we should model things relating to Closure, Factory, Transformer, FluentIterable.forEach, FluentIterable.transform + ";ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", + ";ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", + ";ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", + ";Bag;true;add;;;Argument[0];Element of Argument[-1];value", + ";Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + ";BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", + ";BidiMap;true;removeValue;;;MapKey of Argument[-1];ReturnValue;value", + ";BidiMap;true;inverseBidiMap;;;MapKey of Argument[-1];MapValue of ReturnValue;value", + ";BidiMap;true;inverseBidiMap;;;MapValue of Argument[-1];MapKey of ReturnValue;value", + ";FluentIterable;true;append;(Object[]);;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;append;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;append;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;append;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;asEnumeration;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;collate;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + ";FluentIterable;true;eval;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;filter;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;get;;;Element of Argument[-1];ReturnValue;value", + ";FluentIterable;true;limit;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;loop;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;of;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;of;(Object);;Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;reverse;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", + ";FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", + ";FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;zip;(Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";FluentIterable;true;zip;(Iterable[]);;Element of Argument[-1];Element of ReturnValue;value", + ";FluentIterable;true;zip;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + ";Get;true;entrySet;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", + ";Get;true;entrySet;;;MapValue of Argument[-1];MapValue of Element of ReturnValue;value", + ";Get;true;get;;;MapValue of Argument[-1];ReturnValue;value", + ";Get;true;keySet;();;MapKey of Argument[-1];Element of ReturnValue;value", + ";Get;true;values;();;MapValue of Argument[-1];Element of ReturnValue;value", + ";Get;true;remove;(Object);;MapValue of Argument[-1];ReturnValue;value", + ";IterableGet;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + ";IterableGet;true;mapIterator;;;MapValue of Argument[-1];MapValue of ReturnValue;value", + ";KeyValue;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", + ";KeyValue;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + // Note that MapIterator implements Iterator, so it iterates over the keys of the map. + // In order for the models of Iterator to work we have to use Element instead of MapKey for key data. + ";MapIterator;true;getKey;;;Element of Argument[-1];ReturnValue;value", + ";MapIterator;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + ";MapIterator;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", + ";MapIterator;true;setValue;;;Argument[0];MapValue of Argument[-1];value", + ";MultiMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + ";MultiMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + ";MultiMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + ";MultiMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + ";MultiSet$Entry;true;getElement;;;Element of Argument[-1];ReturnValue;value", + ";MultiSet;true;add;;;Argument[0];Element of Argument[-1];value", + ";MultiSet;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", + ";MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", + ";MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + ";MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", + ";MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + ";MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", + ";MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", + ";MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value", + ";MultiValuedMap;true;mapIterator;;;Element of MapValue of Argument[-1];MapValue of ReturnValue;value", + ";MultiValuedMap;true;put;;;Argument[0];MapKey of Argument[-1];value", + ";MultiValuedMap;true;put;;;Argument[1];Element of MapValue of Argument[-1];value", + ";MultiValuedMap;true;putAll;(Object,Iterable);;Argument[0];MapKey of Argument[-1];value", + ";MultiValuedMap;true;putAll;(Object,Iterable);;Element of Argument[1];Element of MapValue of Argument[-1];value", + ";MultiValuedMap;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + ";MultiValuedMap;true;putAll;(Map);;MapValue of Argument[0];Element of MapValue of Argument[-1];value", + ";MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value", + ";MultiValuedMap;true;putAll;(MultiValuedMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[-1];value", + ";MultiValuedMap;true;remove;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + ";MultiValuedMap;true;values;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", + ";OrderedIterator;true;previous;;;Element of Argument[-1];ReturnValue;value", + ";OrderedMap;true;firstKey;;;MapKey of Argument[-1];ReturnValue;value", + ";OrderedMap;true;lastKey;;;MapKey of Argument[-1];ReturnValue;value", + ";OrderedMap;true;nextKey;;;MapKey of Argument[-1];ReturnValue;value", + ";OrderedMap;true;previousKey;;;MapKey of Argument[-1];ReturnValue;value", + ";Put;true;put;;;MapValue of Argument[-1];ReturnValue;value", + ";Put;true;put;;;Argument[0];MapKey of Argument[-1];value", + ";Put;true;put;;;Argument[1];MapValue of Argument[-1];value", + ";Put;true;putAll;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value", + ";Put;true;putAll;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value", + ";SortedBag;true;first;;;Element of Argument[-1];ReturnValue;value", + ";SortedBag;true;last;;;Element of Argument[-1];ReturnValue;value", + ";Trie;true;prefixMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + ";Trie;true;prefixMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value" + ] } } @@ -228,84 +140,47 @@ private class ApacheCollectionsModel extends SummaryModelCsv { private class ApacheKeyValueModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections4.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections4.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections.keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", - "org.apache.commons.collections.keyvalue;DefaultKeyValue;true;toMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", - "org.apache.commons.collections.keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ".keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[1];MapValue of Argument[-1];value", + ".keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value", + ".keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", + ".keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value", + ".keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", + ".keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", + ".keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[1];MapValue of Argument[-1];value", + ".keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + ".keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", + ".keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", + ".keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[1];MapValue of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;DefaultKeyValue;true;toMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", + ".keyvalue;DefaultKeyValue;true;toMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;DefaultMapEntry;true;DefaultMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;TiedMapEntry;true;TiedMapEntry;;;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;TiedMapEntry;true;TiedMapEntry;;;Argument[1];MapKey of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[0];MapKey of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Object,Object);;Argument[1];MapValue of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(KeyValue);;MapValue of Argument[0];MapValue of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value", + ".keyvalue;UnmodifiableMapEntry;true;UnmodifiableMapEntry;(Entry);;MapValue of Argument[0];MapValue of Argument[-1];value" + ] } } @@ -315,127 +190,69 @@ private class ApacheKeyValueModel extends SummaryModelCsv { private class ApacheMapUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - // Note that when lambdas are supported we should have more models for populateMap - "org.apache.commons.collections4;MapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getMap;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getObject;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;getString;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapKey of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;invertMap;;;MapValue of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;iterableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;iterableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;safeAddToMap;;;Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;safeAddToMap;;;Argument[2];MapValue of Argument[0];value", - "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;synchronizedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;synchronizedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;toMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;toMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;transformedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;transformedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MapUtils;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getMap;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getObject;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;getString;;;Argument[2];ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;invertMap;;;MapKey of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;invertMap;;;MapValue of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;iterableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;iterableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;iterableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;iterableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;safeAddToMap;;;Argument[1];MapKey of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;safeAddToMap;;;Argument[2];MapValue of Argument[0];value", - "org.apache.commons.collections;MapUtils;true;synchronizedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;synchronizedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;synchronizedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;synchronizedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;toMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;toMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;transformedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;transformedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;transformedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;transformedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MapUtils;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + // Note that when lambdas are supported we should have more models for populateMap + ";MapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";MapUtils;true;fixedSizeMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;fixedSizeMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;fixedSizeSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;fixedSizeSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;getMap;;;MapValue of Argument[0];ReturnValue;value", + ";MapUtils;true;getMap;;;Argument[2];ReturnValue;value", + ";MapUtils;true;getObject;;;MapValue of Argument[0];ReturnValue;value", + ";MapUtils;true;getObject;;;Argument[2];ReturnValue;value", + ";MapUtils;true;getString;;;MapValue of Argument[0];ReturnValue;value", + ";MapUtils;true;getString;;;Argument[2];ReturnValue;value", + ";MapUtils;true;invertMap;;;MapKey of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;invertMap;;;MapValue of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;iterableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;iterableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;iterableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;iterableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;lazyMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;lazyMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;lazySortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;lazySortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;multiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;multiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;orderedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;orderedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;populateMap;(Map,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", + ";MapUtils;true;populateMap;(MultiMap,Iterable,Transformer);;Element of Argument[1];MapValue of Argument[0];value", + ";MapUtils;true;predicatedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;predicatedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;predicatedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;predicatedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of Argument[0];value", + ";MapUtils;true;putAll;;;ArrayElement of Argument[1];MapKey of ReturnValue;value", + ";MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of Argument[0];value", + ";MapUtils;true;putAll;;;ArrayElement of Argument[1];MapValue of ReturnValue;value", + ";MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of Argument[0];value", + ";MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapKey of ReturnValue;value", + ";MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of Argument[0];value", + ";MapUtils;true;putAll;;;ArrayElement of ArrayElement of Argument[1];MapValue of ReturnValue;value", + ";MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of Argument[0];value", + ";MapUtils;true;putAll;;;MapKey of ArrayElement of Argument[1];MapKey of ReturnValue;value", + ";MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of Argument[0];value", + ";MapUtils;true;putAll;;;MapValue of ArrayElement of Argument[1];MapValue of ReturnValue;value", + ";MapUtils;true;safeAddToMap;;;Argument[1];MapKey of Argument[0];value", + ";MapUtils;true;safeAddToMap;;;Argument[2];MapValue of Argument[0];value", + ";MapUtils;true;synchronizedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;synchronizedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;synchronizedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;synchronizedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;toMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;toMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;transformedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;transformedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;transformedSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;transformedSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;unmodifiableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;unmodifiableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MapUtils;true;unmodifiableSortedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MapUtils;true;unmodifiableSortedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] } } @@ -445,85 +262,48 @@ private class ApacheMapUtilsModel extends SummaryModelCsv { private class ApacheCollectionUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - // Note that when lambdas are supported we should have a model for collect, forAllButLastDo, forAllDo, transform - "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections4;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections4;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value", - "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", - "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", - "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", - "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections;CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value", - "org.apache.commons.collections;CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value", - "org.apache.commons.collections;CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", - "org.apache.commons.collections;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", - "org.apache.commons.collections;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", - "org.apache.commons.collections;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + // Note that when lambdas are supported we should have a model for collect, forAllButLastDo, forAllDo, transform + ";CollectionUtils;true;addAll;(Collection,Object[]);;ArrayElement of Argument[1];Element of Argument[0];value", + ";CollectionUtils;true;addAll;(Collection,Enumeration);;Element of Argument[1];Element of Argument[0];value", + ";CollectionUtils;true;addAll;(Collection,Iterable);;Element of Argument[1];Element of Argument[0];value", + ";CollectionUtils;true;addAll;(Collection,Iterator);;Element of Argument[1];Element of Argument[0];value", + ";CollectionUtils;true;addIgnoreNull;;;Argument[1];Element of Argument[0];value", + ";CollectionUtils;true;collate;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;collate;;;Element of Argument[1];Element of ReturnValue;value", + ";CollectionUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", + ";CollectionUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";CollectionUtils;true;extractSingleton;;;Element of Argument[0];ReturnValue;value", + ";CollectionUtils;true;find;;;Element of Argument[0];ReturnValue;value", + ";CollectionUtils;true;get;(Iterator,int);;Element of Argument[0];ReturnValue;value", + ";CollectionUtils;true;get;(Iterable,int);;Element of Argument[0];ReturnValue;value", + ";CollectionUtils;true;get;(Map,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + ";CollectionUtils;true;get;(Map,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + ";CollectionUtils;true;get;(Object,int);;ArrayElement of Argument[0];ReturnValue;value", + ";CollectionUtils;true;get;(Object,int);;Element of Argument[0];ReturnValue;value", + ";CollectionUtils;true;get;(Object,int);;MapKey of Argument[0];MapKey of ReturnValue;value", + ";CollectionUtils;true;get;(Object,int);;MapValue of Argument[0];MapValue of ReturnValue;value", + ";CollectionUtils;true;getCardinalityMap;;;Element of Argument[0];MapKey of ReturnValue;value", + ";CollectionUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + ";CollectionUtils;true;permutations;;;Element of Argument[0];Element of Element of ReturnValue;value", + ";CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", + ";CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + ";CollectionUtils;true;unmodifiableCollection;;;Element of Argument[0];Element of ReturnValue;value" + ] } } @@ -533,62 +313,36 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { private class ApacheListUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";ListUtils;true;defaultIfNull;;;Argument[0];ReturnValue;value", + ";ListUtils;true;defaultIfNull;;;Argument[1];ReturnValue;value", + ";ListUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + ";ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", + ";ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", + ";ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;longestCommonSubsequence;(List,List);;Element of Argument[1];Element of ReturnValue;value", + ";ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;longestCommonSubsequence;(List,List,Equator);;Element of Argument[1];Element of ReturnValue;value", + ";ListUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + ";ListUtils;true;predicatedList;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", + ";ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + ";ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + ";ListUtils;true;unmodifiableList;;;Element of Argument[0];Element of ReturnValue;value" + ] } } @@ -598,105 +352,58 @@ private class ApacheListUtilsModel extends SummaryModelCsv { private class ApacheIteratorUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterator - "org.apache.commons.collections4;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", - "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", - "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", - "org.apache.commons.collections4;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", - "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", - "org.apache.commons.collections;IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", - "org.apache.commons.collections;IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterator + ";IteratorUtils;true;arrayIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;arrayListIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;asEnumeration;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;asIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;asIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;asMultipleUseIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;boundedIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;chainedIterator;(Collection);;Element of Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;chainedIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;chainedIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;collatedIterator;(Comparator,Collection);;Element of Element of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;collatedIterator;(Comparator,Iterator[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;collatedIterator;(Comparator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value", + ";IteratorUtils;true;filteredIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", + ";IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", + ";IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", + ";IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;getIterator;;;Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;getIterator;;;MapValue of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;loopingIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;loopingListIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;peekingIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;pushbackIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;singletonIterator;;;Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;singletonListIterator;;;Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;skippingIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", + ";IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + ";IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", + ";IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", + ";IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", + ";IteratorUtils;true;unmodifiableIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;unmodifiableListIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;unmodifiableMapIterator;;;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;unmodifiableMapIterator;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[0];Element of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[1];Element of ReturnValue;value", + ";IteratorUtils;true;zippingIterator;(Iterator,Iterator,Iterator);;Element of Argument[2];Element of ReturnValue;value" + ] } } @@ -705,78 +412,45 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { */ private class ApacheIterableUtilsModel extends SummaryModelCsv { override predicate row(string row) { + // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterable row = - [ - // Note that when lambdas are supported we should have a model for forEach, forEachButLast, transformedIterable - "org.apache.commons.collections4;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", - "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", - "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", - "org.apache.commons.collections4;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", - "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", - "org.apache.commons.collections;IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", - "org.apache.commons.collections;IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";IterableUtils;true;boundedIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable[]);;Element of ArrayElement of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + ";IterableUtils;true;chainedIterable;(Iterable,Iterable,Iterable,Iterable);;Element of Argument[3];Element of ReturnValue;value", + ";IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;collatedIterable;(Comparator,Iterable,Iterable);;Element of Argument[2];Element of ReturnValue;value", + ";IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;collatedIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", + ";IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", + ";IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", + ";IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", + ";IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", + ";IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", + ";IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", + ";IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", + ";IterableUtils;true;uniqueIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;unmodifiableIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;zippingIterable;;;Element of Argument[0];Element of ReturnValue;value", + ";IterableUtils;true;zippingIterable;(Iterable,Iterable[]);;Element of ArrayElement of Argument[1];Element of ReturnValue;value", + ";IterableUtils;true;zippingIterable;(Iterable,Iterable);;Element of Argument[1];Element of ReturnValue;value" + ] } } @@ -786,14 +460,12 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { private class ApacheEnumerationUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint", - "org.apache.commons.collections;EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", - "org.apache.commons.collections;EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";EnumerationUtils;true;get;;;Element of Argument[0];ReturnValue;value", + ";EnumerationUtils;true;toList;(Enumeration);;Element of Argument[0];Element of ReturnValue;value", + ";EnumerationUtils;true;toList;(StringTokenizer);;Argument[0];Element of ReturnValue;taint" + ] } } @@ -803,26 +475,18 @@ private class ApacheEnumerationUtilsModel extends SummaryModelCsv { private class ApacheMultiMapUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", + ";MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", + ";MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", + ";MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", + ";MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] } } @@ -832,14 +496,12 @@ private class ApacheMultiMapUtilsModel extends SummaryModelCsv { private class ApacheMultiSetUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";MultiSetUtils;true;predicatedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + ";MultiSetUtils;true;synchronizedMultiSet;;;Element of Argument[0];Element of ReturnValue;value", + ";MultiSetUtils;true;unmodifiableMultiSet;;;Element of Argument[0];Element of ReturnValue;value" + ] } } @@ -849,16 +511,13 @@ private class ApacheMultiSetUtilsModel extends SummaryModelCsv { private class ApacheQueueUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";QueueUtils;true;predicatedQueue;;;Element of Argument[0];Element of ReturnValue;value", + ";QueueUtils;true;synchronizedQueue;;;Element of Argument[0];Element of ReturnValue;value", + ";QueueUtils;true;transformingQueue;;;Element of Argument[0];Element of ReturnValue;value", + ";QueueUtils;true;unmodifiableQueue;;;Element of Argument[0];Element of ReturnValue;value" + ] } } @@ -869,58 +528,34 @@ private class ApacheQueueUtilsModel extends SummaryModelCsv { private class ApacheSetUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", - "org.apache.commons.collections4;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;hashSet;;;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", - "org.apache.commons.collections;SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;hashSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";SetUtils$SetView;true;copyInto;;;Element of Argument[-1];Element of Argument[0];value", + ";SetUtils$SetView;true;createIterator;;;Element of Argument[-1];Element of ReturnValue;value", + ";SetUtils$SetView;true;toSet;;;Element of Argument[-1];Element of ReturnValue;value", + ";SetUtils;true;difference;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;disjunction;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;disjunction;;;Element of Argument[1];Element of ReturnValue;value", + ";SetUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", + ";SetUtils;true;hashSet;;;ArrayElement of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + ";SetUtils;true;orderedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;predicatedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;predicatedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;predicatedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;synchronizedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;synchronizedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;transformedNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;transformedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;transformedSortedSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", + ";SetUtils;true;unmodifiableNavigableSet;;;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;unmodifiableSet;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;unmodifiableSet;(Set);;Element of Argument[0];Element of ReturnValue;value", + ";SetUtils;true;unmodifiableSortedSet;;;Element of Argument[0];Element of ReturnValue;value" + ] } } @@ -930,16 +565,13 @@ private class ApacheSetUtilsModel extends SummaryModelCsv { private class ApacheSplitMapUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";SplitMapUtils;true;readableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";SplitMapUtils;true;readableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", + ";SplitMapUtils;true;writableMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";SplitMapUtils;true;writableMap;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] } } @@ -949,12 +581,11 @@ private class ApacheSplitMapUtilsModel extends SummaryModelCsv { private class ApacheTrieUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections4;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.collections;TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.collections;TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";TrieUtils;true;unmodifiableTrie;;;MapKey of Argument[0];MapKey of ReturnValue;value", + ";TrieUtils;true;unmodifiableTrie;;;MapValue of Argument[0];MapValue of ReturnValue;value" + ] } } @@ -964,25 +595,17 @@ private class ApacheTrieUtilsModel extends SummaryModelCsv { private class ApacheBagUtilsModel extends SummaryModelCsv { override predicate row(string row) { row = - [ - "org.apache.commons.collections4;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections4;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", - "org.apache.commons.collections;BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" - ] + ["org.apache.commons.collections4", "org.apache.commons.collections"] + + [ + ";BagUtils;true;collectionBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;predicatedBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;predicatedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;synchronizedBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;synchronizedSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;transformingBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;transformingSortedBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;unmodifiableBag;;;Element of Argument[0];Element of ReturnValue;value", + ";BagUtils;true;unmodifiableSortedBag;;;Element of Argument[0];Element of ReturnValue;value" + ] } } From 2d31bb8d64a2915d1ff736938e45ab474dbcf83b Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 9 Aug 2021 16:42:38 +0100 Subject: [PATCH 166/429] Remove toString taint propagation We do not do this for other overrides of toString --- .../java/frameworks/apache/Collections.qll | 7 -- .../frameworks/apache-collections/Test.java | 77 ------------------- 2 files changed, 84 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 0b308406b1c..85a40ebfe59 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -68,7 +68,6 @@ private class ApacheCollectionsModel extends SummaryModelCsv { ";FluentIterable;true;skip;;;Element of Argument[-1];Element of ReturnValue;value", ";FluentIterable;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value", ";FluentIterable;true;toList;;;Element of Argument[-1];Element of ReturnValue;value", - ";FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint", ";FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value", ";FluentIterable;true;unmodifiable;;;Element of Argument[-1];Element of ReturnValue;value", ";FluentIterable;true;zip;(Iterable);;Element of Argument[-1];Element of ReturnValue;value", @@ -148,16 +147,12 @@ private class ApacheKeyValueModel extends SummaryModelCsv { ".keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value", ".keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", ".keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value", - ".keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - ".keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", ".keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value", ".keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[1];MapValue of Argument[-1];value", ".keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapKey of Argument[0];MapKey of Argument[-1];value", ".keyvalue;AbstractMapEntryDecorator;true;AbstractMapEntryDecorator;;;MapValue of Argument[0];MapValue of Argument[-1];value", ".keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapKey of Argument[-1];MapKey of ReturnValue;value", ".keyvalue;AbstractMapEntryDecorator;true;getMapEntry;;;MapValue of Argument[-1];MapValue of ReturnValue;value", - ".keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint", - ".keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint", ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[0];MapKey of Argument[-1];value", ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Object,Object);;Argument[1];MapValue of Argument[-1];value", ".keyvalue;DefaultKeyValue;true;DefaultKeyValue;(KeyValue);;MapKey of Argument[0];MapKey of Argument[-1];value", @@ -389,7 +384,6 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { ";IteratorUtils;true;toArray;;;Element of Argument[0];ArrayElement of ReturnValue;value", ";IteratorUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", ";IteratorUtils;true;toListIterator;;;Element of Argument[0];Element of ReturnValue;value", - ";IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", ";IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint", ";IteratorUtils;true;toString;;;Argument[3];ReturnValue;taint", ";IteratorUtils;true;toString;;;Argument[4];ReturnValue;taint", @@ -441,7 +435,6 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { ";IterableUtils;true;reversedIterable;;;Element of Argument[0];Element of ReturnValue;value", ";IterableUtils;true;skippingIterable;;;Element of Argument[0];Element of ReturnValue;value", ";IterableUtils;true;toList;;;Element of Argument[0];Element of ReturnValue;value", - ";IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint", ";IterableUtils;true;toString;;;Argument[2];ReturnValue;taint", ";IterableUtils;true;toString;;;Argument[3];ReturnValue;taint", ";IterableUtils;true;toString;;;Argument[4];ReturnValue;taint", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 568823a73a4..6b0f678f0d1 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -315,20 +315,6 @@ public class Test { out = in.mySetValue((Object)null); sink(out); // $ hasValueFlow } - { - // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" - String out = null; - AbstractKeyValue in = newMAKVWithMapKey((String)source()); - out = in.toString(); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" - String out = null; - AbstractKeyValue in = newMAKVWithMapValue((String)source()); - out = in.toString(); - sink(out); // $ hasTaintFlow - } { // "org.apache.commons.collections4.keyvalue;AbstractMapEntry;true;AbstractMapEntry;;;Argument[0];MapKey of Argument[-1];value" AbstractMapEntry out = null; @@ -371,20 +357,6 @@ public class Test { out = in.myGetMapEntry(); sink(getMapValueFromEntry(out)); // $ hasValueFlow } - { - // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapKey of Argument[-1];ReturnValue;taint" - String out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapKey((String)source()); - out = in.toString(); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4.keyvalue;AbstractMapEntryDecorator;true;toString;;;MapValue of Argument[-1];ReturnValue;taint" - String out = null; - AbstractMapEntryDecorator in = newMAMEDWithMapValue((String)source()); - out = in.toString(); - sink(out); // $ hasTaintFlow - } { // "org.apache.commons.collections4.keyvalue;DefaultKeyValue;true;DefaultKeyValue;(Entry);;MapKey of Argument[0];MapKey of Argument[-1];value" DefaultKeyValue out = null; @@ -1763,13 +1735,6 @@ public class Test { out = in.toList(); sink(getElement(out)); // $ hasValueFlow } - { - // "org.apache.commons.collections4;FluentIterable;true;toString;;;Element of Argument[-1];ReturnValue;taint" - String out = null; - FluentIterable in = newFluentIterableWithElement((String)source()); - out = in.toString(); - sink(out); // $ hasTaintFlow - } { // "org.apache.commons.collections4;FluentIterable;true;unique;;;Element of Argument[-1];Element of ReturnValue;value" FluentIterable out = null; @@ -2178,27 +2143,6 @@ public class Test { out = IterableUtils.toList(in); sink(getElement(out)); // $ hasValueFlow } - { - // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.toString(in, null, null, null, null); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.toString(in, null); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4;IterableUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterable in = newVectorWithElement((String)source()); - out = IterableUtils.toString(in); - sink(out); // $ hasTaintFlow - } { // "org.apache.commons.collections4;IterableUtils;true;toString;;;Argument[2];ReturnValue;taint" String out = null; @@ -2598,27 +2542,6 @@ public class Test { out = IteratorUtils.toListIterator(in); sink(getElement(out)); // $ hasValueFlow } - { - // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterator in = newListIteratorWithElement((String)source()); - out = IteratorUtils.toString(in, null, null, null, null); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterator in = newListIteratorWithElement((String)source()); - out = IteratorUtils.toString(in, null); - sink(out); // $ hasTaintFlow - } - { - // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Element of Argument[0];ReturnValue;taint" - String out = null; - Iterator in = newListIteratorWithElement((String)source()); - out = IteratorUtils.toString(in); - sink(out); // $ hasTaintFlow - } { // "org.apache.commons.collections4;IteratorUtils;true;toString;;;Argument[2];ReturnValue;taint" String out = null; From 54fdfe39065c279e98d31a489fb9becbc888b598 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 9 Aug 2021 17:14:48 +0100 Subject: [PATCH 167/429] Make helper functions more consistent --- .../frameworks/apache-collections/Test.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 6b0f678f0d1..20559441e51 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -124,7 +124,7 @@ public class Test { MyAbstractMapEntry newMAMEWithMapKey(Object element) { return new MyAbstractMapEntry(element,null); } MyAbstractMapEntryDecorator newMAMEDWithMapKey(Object element) { return new MyAbstractMapEntryDecorator(newMAMEWithMapKey(element)); } MultiValueMap newMVMWithMapKey(Object element) { MultiValueMap m = new MultiValueMap(); m.put(element,null); return m; } - MultiValuedMap newMVdMWithMapKey(Object element) { MultiValuedMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } + ArrayListValuedHashMap newALVHMWithMapKey(Object element) { ArrayListValuedHashMap m = new ArrayListValuedHashMap(); m.put(element,null); return m; } OrderedMapIterator newOMIWithElement(Object element) { LinkedMap m = new LinkedMap(); m.put(element,null); return m.mapIterator(); } ResourceBundle newRBWithMapKey(Object element) { return (ResourceBundle)null; } SortedMap newTreeMapWithMapKey(Object element) { SortedMap m = new TreeMap(); m.put(element,null); return m; } @@ -2944,7 +2944,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = MultiMapUtils.transformedMultiValuedMap(in, null, null); sink(getMapKey(out)); // $ hasValueFlow } @@ -2958,7 +2958,7 @@ public class Test { { // "org.apache.commons.collections4;MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value" MultiValuedMap out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = MultiMapUtils.unmodifiableMultiValuedMap(in); sink(getMapKey(out)); // $ hasValueFlow } @@ -3035,7 +3035,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value" Map out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = in.asMap(); sink(getMapKey(out)); // $ hasValueFlow } @@ -3063,14 +3063,14 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value" Set out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = in.keySet(); sink(getElement(out)); // $ hasValueFlow } { // "org.apache.commons.collections4;MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value" MultiSet out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = in.keys(); sink(getElement(out)); // $ hasValueFlow } @@ -3084,7 +3084,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;mapIterator;;;MapKey of Argument[-1];Element of ReturnValue;value" MapIterator out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out = in.mapIterator(); sink(getElement(out)); // $ hasValueFlow } @@ -3126,7 +3126,7 @@ public class Test { { // "org.apache.commons.collections4;MultiValuedMap;true;putAll;(MultiValuedMap);;MapKey of Argument[0];MapKey of Argument[-1];value" MultiValuedMap out = null; - MultiValuedMap in = newMVdMWithMapKey((String)source()); + MultiValuedMap in = newALVHMWithMapKey((String)source()); out.putAll(in); sink(getMapKey(out)); // $ hasValueFlow } From d1c31db06f313c63959b6a2f8bb798d14ae57e49 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 22 Jul 2021 10:51:54 +0200 Subject: [PATCH 168/429] JS: Reset implicit variable scope when leaving template expr --- .../src/com/semmle/js/extractor/ASTExtractor.java | 5 ++++- .../src/com/semmle/js/extractor/ScopeManager.java | 8 ++++++++ 2 files changed, 12 insertions(+), 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 bb270353869..1bd318d4749 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -732,7 +732,10 @@ public class ASTExtractor { visitAll(nd.getBody(), toplevelLabel); // Leave the local scope again. - if (sourceType.hasLocalScope()) scopeManager.leaveScope(); + if (sourceType.hasLocalScope()) { + scopeManager.leaveScope(); + scopeManager.resetImplicitVariableScope(); + } contextManager.leaveContainer(); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index 923635037c7..b738e875415 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -119,6 +119,14 @@ public class ScopeManager { this.implicitVariableScope = implicitVariableScope; } + /** + * Reset the scope in which to declare variables that are referenced without + * being declared back to the global scope. + */ + public void resetImplicitVariableScope() { + this.implicitVariableScope = toplevelScope; + } + /** * Enter a new scope. * From a7cdf532fa4ef3098c5b3044c6b1315468ebc9fa Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Sat, 17 Jul 2021 14:00:55 +0200 Subject: [PATCH 169/429] JS: Parse mustache-style tags as expressions --- .../src/com/semmle/jcorn/Options.java | 8 +- .../src/com/semmle/jcorn/Parser.java | 47 +- .../src/com/semmle/jcorn/TokenType.java | 2 + .../src/com/semmle/js/ast/DefaultVisitor.java | 5 + .../com/semmle/js/ast/GeneratedCodeExpr.java | 45 ++ .../src/com/semmle/js/ast/NodeCopier.java | 5 + .../src/com/semmle/js/ast/Visitor.java | 2 + .../com/semmle/js/extractor/ASTExtractor.java | 10 +- .../com/semmle/js/extractor/ExprKinds.java | 1 + .../tests/generatedcode/input/tst.js | 9 + .../tests/generatedcode/options.json | 3 + .../generatedcode/output/trap/tst.js.trap | 686 ++++++++++++++++++ javascript/ql/src/semmle/javascript/Expr.qll | 37 + .../semmle/javascript/dataflow/DataFlow.qll | 3 + .../ql/src/semmlecode.javascript.dbscheme | 8 + 15 files changed, 867 insertions(+), 4 deletions(-) create mode 100644 javascript/extractor/src/com/semmle/js/ast/GeneratedCodeExpr.java create mode 100644 javascript/extractor/tests/generatedcode/input/tst.js create mode 100644 javascript/extractor/tests/generatedcode/options.json create mode 100644 javascript/extractor/tests/generatedcode/output/trap/tst.js.trap diff --git a/javascript/extractor/src/com/semmle/jcorn/Options.java b/javascript/extractor/src/com/semmle/jcorn/Options.java index d40998331a0..2a25b2045ad 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Options.java +++ b/javascript/extractor/src/com/semmle/jcorn/Options.java @@ -39,7 +39,7 @@ public class Options { Position endLoc); } - private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere; + private boolean allowHashBang, allowReturnOutsideFunction, allowImportExportEverywhere, allowGeneratedCodeExprs; private boolean preserveParens, mozExtensions, jscript, esnext, v8Extensions, e4x; private int ecmaVersion; private AllowReserved allowReserved; @@ -58,6 +58,7 @@ public class Options { this.allowReserved = AllowReserved.YES; this.allowReturnOutsideFunction = false; this.allowImportExportEverywhere = false; + this.allowGeneratedCodeExprs = true; this.allowHashBang = false; this.onToken = null; this.onComment = null; @@ -75,6 +76,7 @@ public class Options { this.allowHashBang = that.allowHashBang; this.allowReturnOutsideFunction = that.allowReturnOutsideFunction; this.allowImportExportEverywhere = that.allowImportExportEverywhere; + this.allowGeneratedCodeExprs = that.allowGeneratedCodeExprs; this.preserveParens = that.preserveParens; this.mozExtensions = that.mozExtensions; this.jscript = that.jscript; @@ -104,6 +106,10 @@ public class Options { return allowImportExportEverywhere; } + public boolean allowGeneratedCodeExprs() { + return allowGeneratedCodeExprs; + } + public boolean preserveParens() { return preserveParens; } diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index 827b6d4ec03..6dcc13e6770 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -52,6 +52,7 @@ import com.semmle.js.ast.ForOfStatement; import com.semmle.js.ast.ForStatement; import com.semmle.js.ast.FunctionDeclaration; import com.semmle.js.ast.FunctionExpression; +import com.semmle.js.ast.GeneratedCodeExpr; import com.semmle.js.ast.IFunction; import com.semmle.js.ast.INode; import com.semmle.js.ast.IPattern; @@ -537,7 +538,7 @@ public class Parser { } return this.finishOp(TokenType.questionquestion, 2); } - + } return this.finishOp(TokenType.question, 1); } @@ -1929,10 +1930,16 @@ public class Parser { // Parse an object literal or binding pattern. protected Expression parseObj(boolean isPattern, DestructuringErrors refDestructuringErrors) { Position startLoc = this.startLoc; + if (!isPattern && options.allowGeneratedCodeExprs() && charAt(pos) == '{') { + // Parse mustache-style placeholder expression: {{ ... }} or {{{ ... }}} + return charAt(pos + 1) == '{' + ? parseGeneratedCodeExpr(startLoc, "{{{", "}}}") + : parseGeneratedCodeExpr(startLoc, "{{", "}}"); + } boolean first = true; Map propHash = new LinkedHashMap<>(); List properties = new ArrayList(); - this.next(); + this.next(); // skip '{' while (!this.eat(TokenType.braceR)) { if (!first) { this.expect(TokenType.comma); @@ -1949,6 +1956,42 @@ public class Parser { return this.finishNode(node); } + /** Emit a token ranging from the current position until endOfToken. */ + private Token generateTokenEndingAt(int endOfToken, TokenType tokenType) { + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.start = this.pos; + this.startLoc = this.curPosition(); + this.pos = endOfToken; + return finishToken(tokenType); + } + + /** Parse a generated expression. The current token refers to the opening delimiter. */ + protected Expression parseGeneratedCodeExpr(Position startLoc, String openingDelimiter, String closingDelimiter) { + // Emit a token for what's left of the opening delimiter, if there are any remaining characters + int startOfBody = startLoc.getOffset() + openingDelimiter.length(); + if (this.pos != startOfBody) { + this.generateTokenEndingAt(startOfBody, TokenType.generatedCodeDelimiter); + } + + // Emit a token for the generated code body + int endOfBody = this.input.indexOf(closingDelimiter, startOfBody); + if (endOfBody == -1) { + this.unexpected(startLoc); + } + Token bodyToken = this.generateTokenEndingAt(endOfBody, TokenType.generatedCodeExpr); + + // Emit a token for the closing delimiter + this.generateTokenEndingAt(endOfBody + closingDelimiter.length(), TokenType.generatedCodeDelimiter); + + this.next(); // produce lookahead token + + return finishNode(new GeneratedCodeExpr(new SourceLocation(startLoc), openingDelimiter, closingDelimiter, + bodyToken.getValue())); + } + protected Property parseProperty( boolean isPattern, DestructuringErrors refDestructuringErrors, diff --git a/javascript/extractor/src/com/semmle/jcorn/TokenType.java b/javascript/extractor/src/com/semmle/jcorn/TokenType.java index e3c005c1b6a..d8f8c18ce53 100644 --- a/javascript/extractor/src/com/semmle/jcorn/TokenType.java +++ b/javascript/extractor/src/com/semmle/jcorn/TokenType.java @@ -89,6 +89,8 @@ public class TokenType { arrow = new TokenType(new Properties("=>").beforeExpr()), template = new TokenType(new Properties("template")), invalidTemplate = new TokenType(new Properties("invalidTemplate")), + generatedCodeExpr = new TokenType(new Properties("generatedCodeExpr")), + generatedCodeDelimiter = new TokenType(new Properties("generatedCodeDelimiter")), ellipsis = new TokenType(new Properties("...").beforeExpr()), backQuote = new TokenType(new Properties("`").startsExpr()) { diff --git a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java index 4db7dbc400f..995f580edd2 100644 --- a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java @@ -777,4 +777,9 @@ public class DefaultVisitor implements Visitor { public R visit(XMLDotDotExpression nd, C c) { return visit((Expression) nd, c); } + + @Override + public R visit(GeneratedCodeExpr nd, C c) { + return visit((Expression) nd, c); + } } diff --git a/javascript/extractor/src/com/semmle/js/ast/GeneratedCodeExpr.java b/javascript/extractor/src/com/semmle/js/ast/GeneratedCodeExpr.java new file mode 100644 index 00000000000..ec158fdd393 --- /dev/null +++ b/javascript/extractor/src/com/semmle/js/ast/GeneratedCodeExpr.java @@ -0,0 +1,45 @@ +package com.semmle.js.ast; + +/** + * A placeholder for generated code, speculatively parsed as a primary expression. + * + *

    For example, in this snippet, + * + *

    + * let data = {{user_data}};
    + * 
    + * + * the expression {{user_data}} is assumed to be filled in by a templating engine so + * that it can be parsed as an expression, and a GeneratedCodeExpr is thus created to + * represent it. + */ +public class GeneratedCodeExpr extends Expression { + private String openingDelimiter; + private String closingDelimiter; + private String body; + + public GeneratedCodeExpr( + SourceLocation loc, String openingDelimiter, String closingDelimiter, String body) { + super("GeneratedCodeExpr", loc); + this.openingDelimiter = openingDelimiter; + this.closingDelimiter = closingDelimiter; + this.body = body; + } + + public String getOpeningDelimiter() { + return openingDelimiter; + } + + public String getClosingDelimiter() { + return closingDelimiter; + } + + public String getBody() { + return body; + } + + @Override + public R accept(Visitor v, C c) { + return v.visit(this, c); + } +} diff --git a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java index 0a0895d6598..02fd40b12d8 100644 --- a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java +++ b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java @@ -894,4 +894,9 @@ public class NodeCopier implements Visitor { public INode visit(XMLDotDotExpression nd, Void c) { return new XMLDotDotExpression(visit(nd.getLoc()), copy(nd.getLeft()), copy(nd.getRight())); } + + @Override + public INode visit(GeneratedCodeExpr nd, Void c) { + return new GeneratedCodeExpr(visit(nd.getLoc()), nd.getOpeningDelimiter(), nd.getClosingDelimiter(), nd.getBody()); + } } diff --git a/javascript/extractor/src/com/semmle/js/ast/Visitor.java b/javascript/extractor/src/com/semmle/js/ast/Visitor.java index f2a65c83620..f7dfbd4e3aa 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Visitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/Visitor.java @@ -313,4 +313,6 @@ public interface Visitor { public R visit(XMLQualifiedIdentifier nd, C c); public R visit(XMLDotDotExpression nd, C c); + + public R visit(GeneratedCodeExpr generatedCodeExpr, C c); } diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 1bd318d4749..686fa4c6803 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -45,6 +45,7 @@ import com.semmle.js.ast.ForOfStatement; import com.semmle.js.ast.ForStatement; import com.semmle.js.ast.FunctionDeclaration; import com.semmle.js.ast.FunctionExpression; +import com.semmle.js.ast.GeneratedCodeExpr; import com.semmle.js.ast.IFunction; import com.semmle.js.ast.INode; import com.semmle.js.ast.IPattern; @@ -1162,7 +1163,7 @@ public class ASTExtractor { if (!nd.isComputed() && "template".equals(tryGetIdentifierName(nd.getKey()))) { extractStringValueAsHtml(nd.getValue(), valueLabel); } - + return propkey; } @@ -2220,6 +2221,13 @@ public class ASTExtractor { visit(nd.getIdentifier(), key, 0, IdContext.LABEL); return key; } + + @Override + public Label visit(GeneratedCodeExpr nd, Context c) { + Label key = super.visit(nd, c); + trapwriter.addTuple("generated_code_expr_info", key, nd.getOpeningDelimiter(), nd.getClosingDelimiter(), nd.getBody()); + return key; + } } public List extract( diff --git a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java index cfaa252a9f5..9bb5ae766af 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ExprKinds.java @@ -149,6 +149,7 @@ public class ExprKinds { exprKinds.put("ExternalModuleReference", 98); exprKinds.put("NonNullAssertion", 105); exprKinds.put("AngularPipeRef", 119); + exprKinds.put("GeneratedCodeExpr", 120); } private static final Map idKinds = diff --git a/javascript/extractor/tests/generatedcode/input/tst.js b/javascript/extractor/tests/generatedcode/input/tst.js new file mode 100644 index 00000000000..ab13311fe57 --- /dev/null +++ b/javascript/extractor/tests/generatedcode/input/tst.js @@ -0,0 +1,9 @@ +let data1 = {{ user_data1 }}; +let data2 = {{{ user_data2 }}}; +if ({{something}}) {} +foo({{bar}}, {{baz}}); + +{{not_generated_code}} // parse as block +{{ if (not_generated_code) { } }} // parse as block +if (1 == 2) {{not_generated_code}} // parse as block +let string = "{{ not_generated_code }}"; // parse as string literal diff --git a/javascript/extractor/tests/generatedcode/options.json b/javascript/extractor/tests/generatedcode/options.json new file mode 100644 index 00000000000..075583ca1f6 --- /dev/null +++ b/javascript/extractor/tests/generatedcode/options.json @@ -0,0 +1,3 @@ +{ + "experimental": true +} diff --git a/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap b/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap new file mode 100644 index 00000000000..c1293cb897b --- /dev/null +++ b/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap @@ -0,0 +1,686 @@ +#10000=@"/tst.js;sourcefile" +files(#10000,"/tst.js","tst","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=* +comments(#20002,0,#20001," parse as block","// parse as block") +#20003=@"loc,{#10000},6,24,6,40" +locations_default(#20003,#10000,6,24,6,40) +hasLocation(#20002,#20003) +#20004=* +comments(#20004,0,#20001," parse as block","// parse as block") +#20005=@"loc,{#10000},7,35,7,51" +locations_default(#20005,#10000,7,35,7,51) +hasLocation(#20004,#20005) +#20006=* +comments(#20006,0,#20001," parse as block","// parse as block") +#20007=@"loc,{#10000},8,36,8,52" +locations_default(#20007,#10000,8,36,8,52) +hasLocation(#20006,#20007) +#20008=* +comments(#20008,0,#20001," parse as string literal","// pars ... literal") +#20009=@"loc,{#10000},9,42,9,67" +locations_default(#20009,#10000,9,42,9,67) +hasLocation(#20008,#20009) +#20010=* +lines(#20010,#20001,"let data1 = {{ user_data1 }};"," +") +#20011=@"loc,{#10000},1,1,1,29" +locations_default(#20011,#10000,1,1,1,29) +hasLocation(#20010,#20011) +#20012=* +lines(#20012,#20001,"let data2 = {{{ user_data2 }}};"," +") +#20013=@"loc,{#10000},2,1,2,31" +locations_default(#20013,#10000,2,1,2,31) +hasLocation(#20012,#20013) +#20014=* +lines(#20014,#20001,"if ({{something}}) {}"," +") +#20015=@"loc,{#10000},3,1,3,21" +locations_default(#20015,#10000,3,1,3,21) +hasLocation(#20014,#20015) +#20016=* +lines(#20016,#20001,"foo({{bar}}, {{baz}});"," +") +#20017=@"loc,{#10000},4,1,4,22" +locations_default(#20017,#10000,4,1,4,22) +hasLocation(#20016,#20017) +#20018=* +lines(#20018,#20001,""," +") +#20019=@"loc,{#10000},5,1,5,0" +locations_default(#20019,#10000,5,1,5,0) +hasLocation(#20018,#20019) +#20020=* +lines(#20020,#20001,"{{not_generated_code}} // parse as block"," +") +#20021=@"loc,{#10000},6,1,6,40" +locations_default(#20021,#10000,6,1,6,40) +hasLocation(#20020,#20021) +#20022=* +lines(#20022,#20001,"{{ if (not_generated_code) { } }} // parse as block"," +") +#20023=@"loc,{#10000},7,1,7,51" +locations_default(#20023,#10000,7,1,7,51) +hasLocation(#20022,#20023) +#20024=* +lines(#20024,#20001,"if (1 == 2) {{not_generated_code}} // parse as block"," +") +#20025=@"loc,{#10000},8,1,8,52" +locations_default(#20025,#10000,8,1,8,52) +hasLocation(#20024,#20025) +#20026=* +lines(#20026,#20001,"let string = ""{{ not_generated_code }}""; // parse as string literal"," +") +#20027=@"loc,{#10000},9,1,9,67" +locations_default(#20027,#10000,9,1,9,67) +hasLocation(#20026,#20027) +numlines(#20001,9,8,4) +#20028=* +tokeninfo(#20028,7,#20001,0,"let") +#20029=@"loc,{#10000},1,1,1,3" +locations_default(#20029,#10000,1,1,1,3) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,6,#20001,1,"data1") +#20031=@"loc,{#10000},1,5,1,9" +locations_default(#20031,#10000,1,5,1,9) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,8,#20001,2,"=") +#20033=@"loc,{#10000},1,11,1,11" +locations_default(#20033,#10000,1,11,1,11) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,8,#20001,3,"}}") +#20035=@"loc,{#10000},1,27,1,28" +locations_default(#20035,#10000,1,27,1,28) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,4,";") +#20037=@"loc,{#10000},1,29,1,29" +locations_default(#20037,#10000,1,29,1,29) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,7,#20001,5,"let") +#20039=@"loc,{#10000},2,1,2,3" +locations_default(#20039,#10000,2,1,2,3) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,6,#20001,6,"data2") +#20041=@"loc,{#10000},2,5,2,9" +locations_default(#20041,#10000,2,5,2,9) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,8,#20001,7,"=") +#20043=@"loc,{#10000},2,11,2,11" +locations_default(#20043,#10000,2,11,2,11) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,8,#20001,8,"}}}") +#20045=@"loc,{#10000},2,28,2,30" +locations_default(#20045,#10000,2,28,2,30) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,9,";") +#20047=@"loc,{#10000},2,31,2,31" +locations_default(#20047,#10000,2,31,2,31) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,7,#20001,10,"if") +#20049=@"loc,{#10000},3,1,3,2" +locations_default(#20049,#10000,3,1,3,2) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,8,#20001,11,"(") +#20051=@"loc,{#10000},3,4,3,4" +locations_default(#20051,#10000,3,4,3,4) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,8,#20001,12,"}}") +#20053=@"loc,{#10000},3,16,3,17" +locations_default(#20053,#10000,3,16,3,17) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20001,13,")") +#20055=@"loc,{#10000},3,18,3,18" +locations_default(#20055,#10000,3,18,3,18) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,8,#20001,14,"{") +#20057=@"loc,{#10000},3,20,3,20" +locations_default(#20057,#10000,3,20,3,20) +hasLocation(#20056,#20057) +#20058=* +tokeninfo(#20058,8,#20001,15,"}") +#20059=@"loc,{#10000},3,21,3,21" +locations_default(#20059,#10000,3,21,3,21) +hasLocation(#20058,#20059) +#20060=* +tokeninfo(#20060,6,#20001,16,"foo") +#20061=@"loc,{#10000},4,1,4,3" +locations_default(#20061,#10000,4,1,4,3) +hasLocation(#20060,#20061) +#20062=* +tokeninfo(#20062,8,#20001,17,"(") +#20063=@"loc,{#10000},4,4,4,4" +locations_default(#20063,#10000,4,4,4,4) +hasLocation(#20062,#20063) +#20064=* +tokeninfo(#20064,8,#20001,18,"}}") +#20065=@"loc,{#10000},4,10,4,11" +locations_default(#20065,#10000,4,10,4,11) +hasLocation(#20064,#20065) +#20066=* +tokeninfo(#20066,8,#20001,19,",") +#20067=@"loc,{#10000},4,12,4,12" +locations_default(#20067,#10000,4,12,4,12) +hasLocation(#20066,#20067) +#20068=* +tokeninfo(#20068,8,#20001,20,"}}") +#20069=@"loc,{#10000},4,19,4,20" +locations_default(#20069,#10000,4,19,4,20) +hasLocation(#20068,#20069) +#20070=* +tokeninfo(#20070,8,#20001,21,")") +#20071=@"loc,{#10000},4,21,4,21" +locations_default(#20071,#10000,4,21,4,21) +hasLocation(#20070,#20071) +#20072=* +tokeninfo(#20072,8,#20001,22,";") +#20073=@"loc,{#10000},4,22,4,22" +locations_default(#20073,#10000,4,22,4,22) +hasLocation(#20072,#20073) +#20074=* +tokeninfo(#20074,8,#20001,23,"{") +#20075=@"loc,{#10000},6,1,6,1" +locations_default(#20075,#10000,6,1,6,1) +hasLocation(#20074,#20075) +#20076=* +tokeninfo(#20076,8,#20001,24,"{") +#20077=@"loc,{#10000},6,2,6,2" +locations_default(#20077,#10000,6,2,6,2) +hasLocation(#20076,#20077) +#20078=* +tokeninfo(#20078,6,#20001,25,"not_generated_code") +#20079=@"loc,{#10000},6,3,6,20" +locations_default(#20079,#10000,6,3,6,20) +hasLocation(#20078,#20079) +#20080=* +tokeninfo(#20080,8,#20001,26,"}") +#20081=@"loc,{#10000},6,21,6,21" +locations_default(#20081,#10000,6,21,6,21) +hasLocation(#20080,#20081) +#20082=* +tokeninfo(#20082,8,#20001,27,"}") +#20083=@"loc,{#10000},6,22,6,22" +locations_default(#20083,#10000,6,22,6,22) +hasLocation(#20082,#20083) +#20084=* +tokeninfo(#20084,8,#20001,28,"{") +#20085=@"loc,{#10000},7,1,7,1" +locations_default(#20085,#10000,7,1,7,1) +hasLocation(#20084,#20085) +next_token(#20002,#20084) +#20086=* +tokeninfo(#20086,8,#20001,29,"{") +#20087=@"loc,{#10000},7,2,7,2" +locations_default(#20087,#10000,7,2,7,2) +hasLocation(#20086,#20087) +#20088=* +tokeninfo(#20088,7,#20001,30,"if") +#20089=@"loc,{#10000},7,4,7,5" +locations_default(#20089,#10000,7,4,7,5) +hasLocation(#20088,#20089) +#20090=* +tokeninfo(#20090,8,#20001,31,"(") +#20091=@"loc,{#10000},7,7,7,7" +locations_default(#20091,#10000,7,7,7,7) +hasLocation(#20090,#20091) +#20092=* +tokeninfo(#20092,6,#20001,32,"not_generated_code") +#20093=@"loc,{#10000},7,8,7,25" +locations_default(#20093,#10000,7,8,7,25) +hasLocation(#20092,#20093) +#20094=* +tokeninfo(#20094,8,#20001,33,")") +#20095=@"loc,{#10000},7,26,7,26" +locations_default(#20095,#10000,7,26,7,26) +hasLocation(#20094,#20095) +#20096=* +tokeninfo(#20096,8,#20001,34,"{") +#20097=@"loc,{#10000},7,28,7,28" +locations_default(#20097,#10000,7,28,7,28) +hasLocation(#20096,#20097) +#20098=* +tokeninfo(#20098,8,#20001,35,"}") +#20099=@"loc,{#10000},7,30,7,30" +locations_default(#20099,#10000,7,30,7,30) +hasLocation(#20098,#20099) +#20100=* +tokeninfo(#20100,8,#20001,36,"}") +#20101=@"loc,{#10000},7,32,7,32" +locations_default(#20101,#10000,7,32,7,32) +hasLocation(#20100,#20101) +#20102=* +tokeninfo(#20102,8,#20001,37,"}") +#20103=@"loc,{#10000},7,33,7,33" +locations_default(#20103,#10000,7,33,7,33) +hasLocation(#20102,#20103) +#20104=* +tokeninfo(#20104,7,#20001,38,"if") +#20105=@"loc,{#10000},8,1,8,2" +locations_default(#20105,#10000,8,1,8,2) +hasLocation(#20104,#20105) +next_token(#20004,#20104) +#20106=* +tokeninfo(#20106,8,#20001,39,"(") +#20107=@"loc,{#10000},8,4,8,4" +locations_default(#20107,#10000,8,4,8,4) +hasLocation(#20106,#20107) +#20108=* +tokeninfo(#20108,3,#20001,40,"1") +#20109=@"loc,{#10000},8,5,8,5" +locations_default(#20109,#10000,8,5,8,5) +hasLocation(#20108,#20109) +#20110=* +tokeninfo(#20110,8,#20001,41,"==") +#20111=@"loc,{#10000},8,7,8,8" +locations_default(#20111,#10000,8,7,8,8) +hasLocation(#20110,#20111) +#20112=* +tokeninfo(#20112,3,#20001,42,"2") +#20113=@"loc,{#10000},8,10,8,10" +locations_default(#20113,#10000,8,10,8,10) +hasLocation(#20112,#20113) +#20114=* +tokeninfo(#20114,8,#20001,43,")") +#20115=@"loc,{#10000},8,11,8,11" +locations_default(#20115,#10000,8,11,8,11) +hasLocation(#20114,#20115) +#20116=* +tokeninfo(#20116,8,#20001,44,"{") +#20117=@"loc,{#10000},8,13,8,13" +locations_default(#20117,#10000,8,13,8,13) +hasLocation(#20116,#20117) +#20118=* +tokeninfo(#20118,8,#20001,45,"{") +#20119=@"loc,{#10000},8,14,8,14" +locations_default(#20119,#10000,8,14,8,14) +hasLocation(#20118,#20119) +#20120=* +tokeninfo(#20120,6,#20001,46,"not_generated_code") +#20121=@"loc,{#10000},8,15,8,32" +locations_default(#20121,#10000,8,15,8,32) +hasLocation(#20120,#20121) +#20122=* +tokeninfo(#20122,8,#20001,47,"}") +#20123=@"loc,{#10000},8,33,8,33" +locations_default(#20123,#10000,8,33,8,33) +hasLocation(#20122,#20123) +#20124=* +tokeninfo(#20124,8,#20001,48,"}") +#20125=@"loc,{#10000},8,34,8,34" +locations_default(#20125,#10000,8,34,8,34) +hasLocation(#20124,#20125) +#20126=* +tokeninfo(#20126,7,#20001,49,"let") +#20127=@"loc,{#10000},9,1,9,3" +locations_default(#20127,#10000,9,1,9,3) +hasLocation(#20126,#20127) +next_token(#20006,#20126) +#20128=* +tokeninfo(#20128,6,#20001,50,"string") +#20129=@"loc,{#10000},9,5,9,10" +locations_default(#20129,#10000,9,5,9,10) +hasLocation(#20128,#20129) +#20130=* +tokeninfo(#20130,8,#20001,51,"=") +#20131=@"loc,{#10000},9,12,9,12" +locations_default(#20131,#10000,9,12,9,12) +hasLocation(#20130,#20131) +#20132=* +tokeninfo(#20132,4,#20001,52,"""{{ not_generated_code }}""") +#20133=@"loc,{#10000},9,14,9,39" +locations_default(#20133,#10000,9,14,9,39) +hasLocation(#20132,#20133) +#20134=* +tokeninfo(#20134,8,#20001,53,";") +#20135=@"loc,{#10000},9,40,9,40" +locations_default(#20135,#10000,9,40,9,40) +hasLocation(#20134,#20135) +#20136=* +tokeninfo(#20136,0,#20001,54,"") +#20137=@"loc,{#10000},10,1,10,0" +locations_default(#20137,#10000,10,1,10,0) +hasLocation(#20136,#20137) +next_token(#20008,#20136) +toplevels(#20001,0) +#20138=@"loc,{#10000},1,1,10,0" +locations_default(#20138,#10000,1,1,10,0) +hasLocation(#20001,#20138) +#20139=@"var;{data1};{#20000}" +variables(#20139,"data1",#20000) +#20140=@"var;{data2};{#20000}" +variables(#20140,"data2",#20000) +#20141=@"var;{string};{#20000}" +variables(#20141,"string",#20000) +#20142=* +stmts(#20142,23,#20001,0,"let dat ... ta1 }};") +hasLocation(#20142,#20011) +stmt_containers(#20142,#20001) +#20143=* +exprs(#20143,64,#20142,0,"data1 = ... ata1 }}") +#20144=@"loc,{#10000},1,5,1,28" +locations_default(#20144,#10000,1,5,1,28) +hasLocation(#20143,#20144) +enclosing_stmt(#20143,#20142) +expr_containers(#20143,#20001) +#20145=* +exprs(#20145,78,#20143,0,"data1") +hasLocation(#20145,#20031) +enclosing_stmt(#20145,#20142) +expr_containers(#20145,#20001) +literals("data1","data1",#20145) +decl(#20145,#20139) +#20146=* +exprs(#20146,120,#20143,1,"{{ user_data1 }}") +#20147=@"loc,{#10000},1,13,1,28" +locations_default(#20147,#10000,1,13,1,28) +hasLocation(#20146,#20147) +enclosing_stmt(#20146,#20142) +expr_containers(#20146,#20001) +generated_code_expr_info(#20146,"{{","}}"," user_data1 ") +#20148=* +stmts(#20148,23,#20001,1,"let dat ... a2 }}};") +hasLocation(#20148,#20013) +stmt_containers(#20148,#20001) +#20149=* +exprs(#20149,64,#20148,0,"data2 = ... ta2 }}}") +#20150=@"loc,{#10000},2,5,2,30" +locations_default(#20150,#10000,2,5,2,30) +hasLocation(#20149,#20150) +enclosing_stmt(#20149,#20148) +expr_containers(#20149,#20001) +#20151=* +exprs(#20151,78,#20149,0,"data2") +hasLocation(#20151,#20041) +enclosing_stmt(#20151,#20148) +expr_containers(#20151,#20001) +literals("data2","data2",#20151) +decl(#20151,#20140) +#20152=* +exprs(#20152,120,#20149,1,"{{{ user_data2 }}}") +#20153=@"loc,{#10000},2,13,2,30" +locations_default(#20153,#10000,2,13,2,30) +hasLocation(#20152,#20153) +enclosing_stmt(#20152,#20148) +expr_containers(#20152,#20001) +generated_code_expr_info(#20152,"{{{","}}}"," user_data2 ") +#20154=* +stmts(#20154,3,#20001,2,"if ({{s ... g}}) {}") +hasLocation(#20154,#20015) +stmt_containers(#20154,#20001) +#20155=* +exprs(#20155,120,#20154,0,"{{something}}") +#20156=@"loc,{#10000},3,5,3,17" +locations_default(#20156,#10000,3,5,3,17) +hasLocation(#20155,#20156) +enclosing_stmt(#20155,#20154) +expr_containers(#20155,#20001) +generated_code_expr_info(#20155,"{{","}}","something") +#20157=* +stmts(#20157,1,#20154,1,"{}") +#20158=@"loc,{#10000},3,20,3,21" +locations_default(#20158,#10000,3,20,3,21) +hasLocation(#20157,#20158) +stmt_containers(#20157,#20001) +#20159=* +stmts(#20159,2,#20001,3,"foo({{b ... baz}});") +hasLocation(#20159,#20017) +stmt_containers(#20159,#20001) +#20160=* +exprs(#20160,13,#20159,0,"foo({{b ... {baz}})") +#20161=@"loc,{#10000},4,1,4,21" +locations_default(#20161,#10000,4,1,4,21) +hasLocation(#20160,#20161) +enclosing_stmt(#20160,#20159) +expr_containers(#20160,#20001) +#20162=* +exprs(#20162,79,#20160,-1,"foo") +hasLocation(#20162,#20061) +enclosing_stmt(#20162,#20159) +expr_containers(#20162,#20001) +literals("foo","foo",#20162) +#20163=@"var;{foo};{#20000}" +variables(#20163,"foo",#20000) +bind(#20162,#20163) +#20164=* +exprs(#20164,120,#20160,0,"{{bar}}") +#20165=@"loc,{#10000},4,5,4,11" +locations_default(#20165,#10000,4,5,4,11) +hasLocation(#20164,#20165) +enclosing_stmt(#20164,#20159) +expr_containers(#20164,#20001) +generated_code_expr_info(#20164,"{{","}}","bar") +#20166=* +exprs(#20166,120,#20160,1,"{{baz}}") +#20167=@"loc,{#10000},4,14,4,20" +locations_default(#20167,#10000,4,14,4,20) +hasLocation(#20166,#20167) +enclosing_stmt(#20166,#20159) +expr_containers(#20166,#20001) +generated_code_expr_info(#20166,"{{","}}","baz") +#20168=* +stmts(#20168,1,#20001,4,"{{not_g ... _code}}") +#20169=@"loc,{#10000},6,1,6,22" +locations_default(#20169,#10000,6,1,6,22) +hasLocation(#20168,#20169) +stmt_containers(#20168,#20001) +#20170=* +stmts(#20170,1,#20168,0,"{not_generated_code}") +#20171=@"loc,{#10000},6,2,6,21" +locations_default(#20171,#10000,6,2,6,21) +hasLocation(#20170,#20171) +stmt_containers(#20170,#20001) +#20172=* +stmts(#20172,2,#20170,0,"not_generated_code") +hasLocation(#20172,#20079) +stmt_containers(#20172,#20001) +#20173=* +exprs(#20173,79,#20172,0,"not_generated_code") +hasLocation(#20173,#20079) +enclosing_stmt(#20173,#20172) +expr_containers(#20173,#20001) +literals("not_generated_code","not_generated_code",#20173) +#20174=@"var;{not_generated_code};{#20000}" +variables(#20174,"not_generated_code",#20000) +bind(#20173,#20174) +#20175=* +stmts(#20175,1,#20001,5,"{{ if ( ... { } }}") +#20176=@"loc,{#10000},7,1,7,33" +locations_default(#20176,#10000,7,1,7,33) +hasLocation(#20175,#20176) +stmt_containers(#20175,#20001) +#20177=* +stmts(#20177,1,#20175,0,"{ if (n ... ) { } }") +#20178=@"loc,{#10000},7,2,7,32" +locations_default(#20178,#10000,7,2,7,32) +hasLocation(#20177,#20178) +stmt_containers(#20177,#20001) +#20179=* +stmts(#20179,3,#20177,0,"if (not ... de) { }") +#20180=@"loc,{#10000},7,4,7,30" +locations_default(#20180,#10000,7,4,7,30) +hasLocation(#20179,#20180) +stmt_containers(#20179,#20001) +#20181=* +exprs(#20181,79,#20179,0,"not_generated_code") +hasLocation(#20181,#20093) +enclosing_stmt(#20181,#20179) +expr_containers(#20181,#20001) +literals("not_generated_code","not_generated_code",#20181) +bind(#20181,#20174) +#20182=* +stmts(#20182,1,#20179,1,"{ }") +#20183=@"loc,{#10000},7,28,7,30" +locations_default(#20183,#10000,7,28,7,30) +hasLocation(#20182,#20183) +stmt_containers(#20182,#20001) +#20184=* +stmts(#20184,3,#20001,6,"if (1 = ... _code}}") +#20185=@"loc,{#10000},8,1,8,34" +locations_default(#20185,#10000,8,1,8,34) +hasLocation(#20184,#20185) +stmt_containers(#20184,#20001) +#20186=* +exprs(#20186,23,#20184,0,"1 == 2") +#20187=@"loc,{#10000},8,5,8,10" +locations_default(#20187,#10000,8,5,8,10) +hasLocation(#20186,#20187) +enclosing_stmt(#20186,#20184) +expr_containers(#20186,#20001) +#20188=* +exprs(#20188,3,#20186,0,"1") +hasLocation(#20188,#20109) +enclosing_stmt(#20188,#20184) +expr_containers(#20188,#20001) +literals("1","1",#20188) +#20189=* +exprs(#20189,3,#20186,1,"2") +hasLocation(#20189,#20113) +enclosing_stmt(#20189,#20184) +expr_containers(#20189,#20001) +literals("2","2",#20189) +#20190=* +stmts(#20190,1,#20184,1,"{{not_g ... _code}}") +#20191=@"loc,{#10000},8,13,8,34" +locations_default(#20191,#10000,8,13,8,34) +hasLocation(#20190,#20191) +stmt_containers(#20190,#20001) +#20192=* +stmts(#20192,1,#20190,0,"{not_generated_code}") +#20193=@"loc,{#10000},8,14,8,33" +locations_default(#20193,#10000,8,14,8,33) +hasLocation(#20192,#20193) +stmt_containers(#20192,#20001) +#20194=* +stmts(#20194,2,#20192,0,"not_generated_code") +hasLocation(#20194,#20121) +stmt_containers(#20194,#20001) +#20195=* +exprs(#20195,79,#20194,0,"not_generated_code") +hasLocation(#20195,#20121) +enclosing_stmt(#20195,#20194) +expr_containers(#20195,#20001) +literals("not_generated_code","not_generated_code",#20195) +bind(#20195,#20174) +#20196=* +stmts(#20196,23,#20001,7,"let str ... de }}"";") +#20197=@"loc,{#10000},9,1,9,40" +locations_default(#20197,#10000,9,1,9,40) +hasLocation(#20196,#20197) +stmt_containers(#20196,#20001) +#20198=* +exprs(#20198,64,#20196,0,"string ... ode }}""") +#20199=@"loc,{#10000},9,5,9,39" +locations_default(#20199,#10000,9,5,9,39) +hasLocation(#20198,#20199) +enclosing_stmt(#20198,#20196) +expr_containers(#20198,#20001) +#20200=* +exprs(#20200,78,#20198,0,"string") +hasLocation(#20200,#20129) +enclosing_stmt(#20200,#20196) +expr_containers(#20200,#20001) +literals("string","string",#20200) +decl(#20200,#20141) +#20201=* +exprs(#20201,4,#20198,1,"""{{ not ... ode }}""") +hasLocation(#20201,#20133) +enclosing_stmt(#20201,#20196) +expr_containers(#20201,#20001) +literals("{{ not_generated_code }}","""{{ not_generated_code }}""",#20201) +#20202=* +entry_cfg_node(#20202,#20001) +#20203=@"loc,{#10000},1,1,1,0" +locations_default(#20203,#10000,1,1,1,0) +hasLocation(#20202,#20203) +#20204=* +exit_cfg_node(#20204,#20001) +hasLocation(#20204,#20137) +successor(#20196,#20200) +successor(#20201,#20198) +successor(#20200,#20201) +successor(#20198,#20204) +successor(#20184,#20188) +successor(#20189,#20186) +successor(#20188,#20189) +#20205=* +guard_node(#20205,1,#20186) +hasLocation(#20205,#20187) +successor(#20205,#20190) +#20206=* +guard_node(#20206,0,#20186) +hasLocation(#20206,#20187) +successor(#20206,#20196) +successor(#20186,#20205) +successor(#20186,#20206) +successor(#20190,#20192) +successor(#20192,#20194) +successor(#20194,#20195) +successor(#20195,#20196) +successor(#20175,#20177) +successor(#20177,#20179) +successor(#20179,#20181) +#20207=* +guard_node(#20207,1,#20181) +hasLocation(#20207,#20093) +successor(#20207,#20182) +#20208=* +guard_node(#20208,0,#20181) +hasLocation(#20208,#20093) +successor(#20208,#20184) +successor(#20181,#20207) +successor(#20181,#20208) +successor(#20182,#20184) +successor(#20168,#20170) +successor(#20170,#20172) +successor(#20172,#20173) +successor(#20173,#20175) +successor(#20159,#20162) +successor(#20166,#20160) +successor(#20164,#20166) +successor(#20162,#20164) +successor(#20160,#20168) +successor(#20154,#20155) +#20209=* +guard_node(#20209,1,#20155) +hasLocation(#20209,#20156) +successor(#20209,#20157) +#20210=* +guard_node(#20210,0,#20155) +hasLocation(#20210,#20156) +successor(#20210,#20159) +successor(#20155,#20209) +successor(#20155,#20210) +successor(#20157,#20159) +successor(#20148,#20151) +successor(#20152,#20149) +successor(#20151,#20152) +successor(#20149,#20154) +successor(#20142,#20145) +successor(#20146,#20143) +successor(#20145,#20146) +successor(#20143,#20148) +successor(#20202,#20142) +numlines(#10000,9,8,4) +filetype(#10000,"javascript") diff --git a/javascript/ql/src/semmle/javascript/Expr.qll b/javascript/ql/src/semmle/javascript/Expr.qll index 95181c376bf..bc8cb8c7f98 100644 --- a/javascript/ql/src/semmle/javascript/Expr.qll +++ b/javascript/ql/src/semmle/javascript/Expr.qll @@ -2873,3 +2873,40 @@ class ImportMetaExpr extends @import_meta_expr, Expr { override string getAPrimaryQlClass() { result = "ImportMetaExpr" } } + +/** + * A placeholder for some code generated by a templating engine, + * speculatively parsed as an expression. + * + * For example, the right-hand side of the following assignments will each be parsed + * as `GeneratedNodeExpr` nodes: + * ```js + * let data1 = {{ user_data1 }}; + * let data2 = {{{ user_data2 }}}; + * ``` + * + * Note that templating placeholders occuring inside strings literals are not parsed, + * and are simply seen as being part of the string literal. + * For example, following snippet does not contain any `GeneratedCodeExpr` nodes: + * ```js + * let data1 = "{{ user_data }}"; + * ``` + */ +class GeneratedCodeExpr extends @generated_code_expr, Expr { + /** Gets the opening delimiter, such as `{{` or `{{{`. */ + string getOpeningDelimiter() { + generated_code_expr_info(this, result, _, _) + } + + /** Gets the closing delimiter, such as `}}` or `}}}`. */ + string getClosingDelimiter() { + generated_code_expr_info(this, _, result, _) + } + + /** Gets the text between the delimiters, including any surrounding whitespace, such as the `x` in `{{x}}`. */ + string getBody() { + generated_code_expr_info(this, _, _, result) + } + + override string getAPrimaryQlClass() { result = "GeneratedCodeExpr" } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index f02e9b0f287..06111e8367e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -1654,6 +1654,9 @@ module DataFlow { or (e instanceof AwaitExpr or e instanceof DynamicImportExpr) and cause = "await" + or + e instanceof GeneratedCodeExpr and + cause = "eval" // we use 'eval' here to represent code generation more broadly ) or nd instanceof TExceptionalInvocationReturnNode and cause = "call" diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index fbd45f6b3c6..8dc6eda996a 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -366,6 +366,7 @@ case @expr.kind of | 117 = @assignlogorexpr | 118 = @assignnullishcoalescingexpr | 119 = @angular_pipe_ref +| 120 = @generated_code_expr ; @varaccess = @proper_varaccess | @export_varaccess; @@ -416,6 +417,13 @@ case @expr.kind of @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; +generated_code_expr_info( + unique int expr: @generated_code_expr ref, + varchar(900) openingDelimiter: string ref, + varchar(900) closingDelimiter: string ref, + varchar(900) body: string ref +); + // scopes scopes (unique int id: @scope, int kind: int ref); From e678c16d5981efb667ca365935548e869a5a24a4 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Sat, 17 Jul 2021 14:46:59 +0200 Subject: [PATCH 170/429] JS: Parse EJS-style template tags --- .../src/com/semmle/jcorn/Parser.java | 12 + .../src/com/semmle/jcorn/TokenType.java | 4 +- .../src/com/semmle/jcorn/jsx/JSXParser.java | 5 +- .../tests/generatedcode/input/ejs.js | 7 + .../generatedcode/output/trap/ejs.js.trap | 410 ++++++++++++++++++ 5 files changed, 435 insertions(+), 3 deletions(-) create mode 100644 javascript/extractor/tests/generatedcode/input/ejs.js create mode 100644 javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index 6dcc13e6770..5f7383813c6 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -618,6 +618,15 @@ public class Parser { this.skipSpace(); return this.nextToken(); } + if (next == '%' && code == '<' && this.options.allowGeneratedCodeExprs()) { + // `<%`, the beginning of an EJS-style template tag + size = 2; + int nextNext = charAt(this.pos + 2); + if (nextNext == '=' || nextNext == '-') { + ++size; + } + return this.finishOp(TokenType.generatedCodeDelimiterEJS, size); + } if (next == 61) size = 2; return this.finishOp(TokenType.relational, size); } @@ -1689,6 +1698,9 @@ public class Parser { return this.parseNew(); } else if (this.type == TokenType.backQuote) { return this.parseTemplate(false); + } else if (this.type == TokenType.generatedCodeDelimiterEJS) { + String openingDelimiter = (String) this.value; + return this.parseGeneratedCodeExpr(this.startLoc, openingDelimiter, "%>"); } else { this.unexpected(); return null; diff --git a/javascript/extractor/src/com/semmle/jcorn/TokenType.java b/javascript/extractor/src/com/semmle/jcorn/TokenType.java index d8f8c18ce53..a0e06bdd3eb 100644 --- a/javascript/extractor/src/com/semmle/jcorn/TokenType.java +++ b/javascript/extractor/src/com/semmle/jcorn/TokenType.java @@ -1,9 +1,10 @@ package com.semmle.jcorn; -import com.semmle.jcorn.Parser.TokContext; import java.util.LinkedHashMap; import java.util.Map; +import com.semmle.jcorn.Parser.TokContext; + /// tokentype.js // ## Token types @@ -91,6 +92,7 @@ public class TokenType { invalidTemplate = new TokenType(new Properties("invalidTemplate")), generatedCodeExpr = new TokenType(new Properties("generatedCodeExpr")), generatedCodeDelimiter = new TokenType(new Properties("generatedCodeDelimiter")), + generatedCodeDelimiterEJS = new TokenType(new Properties("<%/%>")), ellipsis = new TokenType(new Properties("...").beforeExpr()), backQuote = new TokenType(new Properties("`").startsExpr()) { diff --git a/javascript/extractor/src/com/semmle/jcorn/jsx/JSXParser.java b/javascript/extractor/src/com/semmle/jcorn/jsx/JSXParser.java index ee5ef3dc29f..6deec72809c 100644 --- a/javascript/extractor/src/com/semmle/jcorn/jsx/JSXParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/jsx/JSXParser.java @@ -420,8 +420,9 @@ public class JSXParser extends Parser { && code == 60 && this.exprAllowed && - // avoid getting confused on HTML comments - this.charAt(this.pos + 1) != '!') { + // avoid getting confused on HTML comments or EJS-style template tags + this.charAt(this.pos + 1) != '!' && + this.charAt(this.pos + 1) != '%') { ++this.pos; return this.finishToken(jsxTagStart); } diff --git a/javascript/extractor/tests/generatedcode/input/ejs.js b/javascript/extractor/tests/generatedcode/input/ejs.js new file mode 100644 index 00000000000..0c720509889 --- /dev/null +++ b/javascript/extractor/tests/generatedcode/input/ejs.js @@ -0,0 +1,7 @@ +let data1 = <%= user_data1 %>; +let data2 = <%- user_data2 %>; +if (<%something%>) {} +foo(<%bar%>, <%baz%>); + +<% generated_code %> +let string = "<%= not_generated_code %>"; // parse as string literal diff --git a/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap b/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap new file mode 100644 index 00000000000..cebf13a3fda --- /dev/null +++ b/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap @@ -0,0 +1,410 @@ +#10000=@"/ejs.js;sourcefile" +files(#10000,"/ejs.js","ejs","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=* +comments(#20002,0,#20001," parse as string literal","// pars ... literal") +#20003=@"loc,{#10000},7,43,7,68" +locations_default(#20003,#10000,7,43,7,68) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001,"let data1 = <%= user_data1 %>;"," +") +#20005=@"loc,{#10000},1,1,1,30" +locations_default(#20005,#10000,1,1,1,30) +hasLocation(#20004,#20005) +#20006=* +lines(#20006,#20001,"let data2 = <%- user_data2 %>;"," +") +#20007=@"loc,{#10000},2,1,2,30" +locations_default(#20007,#10000,2,1,2,30) +hasLocation(#20006,#20007) +#20008=* +lines(#20008,#20001,"if (<%something%>) {}"," +") +#20009=@"loc,{#10000},3,1,3,21" +locations_default(#20009,#10000,3,1,3,21) +hasLocation(#20008,#20009) +#20010=* +lines(#20010,#20001,"foo(<%bar%>, <%baz%>);"," +") +#20011=@"loc,{#10000},4,1,4,22" +locations_default(#20011,#10000,4,1,4,22) +hasLocation(#20010,#20011) +#20012=* +lines(#20012,#20001,""," +") +#20013=@"loc,{#10000},5,1,5,0" +locations_default(#20013,#10000,5,1,5,0) +hasLocation(#20012,#20013) +#20014=* +lines(#20014,#20001,"<% generated_code %>"," +") +#20015=@"loc,{#10000},6,1,6,20" +locations_default(#20015,#10000,6,1,6,20) +hasLocation(#20014,#20015) +#20016=* +lines(#20016,#20001,"let string = ""<%= not_generated_code %>""; // parse as string literal"," +") +#20017=@"loc,{#10000},7,1,7,68" +locations_default(#20017,#10000,7,1,7,68) +hasLocation(#20016,#20017) +numlines(#20001,7,6,1) +#20018=* +tokeninfo(#20018,7,#20001,0,"let") +#20019=@"loc,{#10000},1,1,1,3" +locations_default(#20019,#10000,1,1,1,3) +hasLocation(#20018,#20019) +#20020=* +tokeninfo(#20020,6,#20001,1,"data1") +#20021=@"loc,{#10000},1,5,1,9" +locations_default(#20021,#10000,1,5,1,9) +hasLocation(#20020,#20021) +#20022=* +tokeninfo(#20022,8,#20001,2,"=") +#20023=@"loc,{#10000},1,11,1,11" +locations_default(#20023,#10000,1,11,1,11) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,8,#20001,3,"%>") +#20025=@"loc,{#10000},1,28,1,29" +locations_default(#20025,#10000,1,28,1,29) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,8,#20001,4,";") +#20027=@"loc,{#10000},1,30,1,30" +locations_default(#20027,#10000,1,30,1,30) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,7,#20001,5,"let") +#20029=@"loc,{#10000},2,1,2,3" +locations_default(#20029,#10000,2,1,2,3) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,6,#20001,6,"data2") +#20031=@"loc,{#10000},2,5,2,9" +locations_default(#20031,#10000,2,5,2,9) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,8,#20001,7,"=") +#20033=@"loc,{#10000},2,11,2,11" +locations_default(#20033,#10000,2,11,2,11) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,8,#20001,8,"%>") +#20035=@"loc,{#10000},2,28,2,29" +locations_default(#20035,#10000,2,28,2,29) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,8,#20001,9,";") +#20037=@"loc,{#10000},2,30,2,30" +locations_default(#20037,#10000,2,30,2,30) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,7,#20001,10,"if") +#20039=@"loc,{#10000},3,1,3,2" +locations_default(#20039,#10000,3,1,3,2) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,8,#20001,11,"(") +#20041=@"loc,{#10000},3,4,3,4" +locations_default(#20041,#10000,3,4,3,4) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,8,#20001,12,"%>") +#20043=@"loc,{#10000},3,16,3,17" +locations_default(#20043,#10000,3,16,3,17) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,8,#20001,13,")") +#20045=@"loc,{#10000},3,18,3,18" +locations_default(#20045,#10000,3,18,3,18) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,14,"{") +#20047=@"loc,{#10000},3,20,3,20" +locations_default(#20047,#10000,3,20,3,20) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,8,#20001,15,"}") +#20049=@"loc,{#10000},3,21,3,21" +locations_default(#20049,#10000,3,21,3,21) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,6,#20001,16,"foo") +#20051=@"loc,{#10000},4,1,4,3" +locations_default(#20051,#10000,4,1,4,3) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,8,#20001,17,"(") +#20053=@"loc,{#10000},4,4,4,4" +locations_default(#20053,#10000,4,4,4,4) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20001,18,"%>") +#20055=@"loc,{#10000},4,10,4,11" +locations_default(#20055,#10000,4,10,4,11) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,8,#20001,19,",") +#20057=@"loc,{#10000},4,12,4,12" +locations_default(#20057,#10000,4,12,4,12) +hasLocation(#20056,#20057) +#20058=* +tokeninfo(#20058,8,#20001,20,"%>") +#20059=@"loc,{#10000},4,19,4,20" +locations_default(#20059,#10000,4,19,4,20) +hasLocation(#20058,#20059) +#20060=* +tokeninfo(#20060,8,#20001,21,")") +#20061=@"loc,{#10000},4,21,4,21" +locations_default(#20061,#10000,4,21,4,21) +hasLocation(#20060,#20061) +#20062=* +tokeninfo(#20062,8,#20001,22,";") +#20063=@"loc,{#10000},4,22,4,22" +locations_default(#20063,#10000,4,22,4,22) +hasLocation(#20062,#20063) +#20064=* +tokeninfo(#20064,8,#20001,23,"%>") +#20065=@"loc,{#10000},6,19,6,20" +locations_default(#20065,#10000,6,19,6,20) +hasLocation(#20064,#20065) +#20066=* +tokeninfo(#20066,7,#20001,24,"let") +#20067=@"loc,{#10000},7,1,7,3" +locations_default(#20067,#10000,7,1,7,3) +hasLocation(#20066,#20067) +#20068=* +tokeninfo(#20068,6,#20001,25,"string") +#20069=@"loc,{#10000},7,5,7,10" +locations_default(#20069,#10000,7,5,7,10) +hasLocation(#20068,#20069) +#20070=* +tokeninfo(#20070,8,#20001,26,"=") +#20071=@"loc,{#10000},7,12,7,12" +locations_default(#20071,#10000,7,12,7,12) +hasLocation(#20070,#20071) +#20072=* +tokeninfo(#20072,4,#20001,27,"""<%= not_generated_code %>""") +#20073=@"loc,{#10000},7,14,7,40" +locations_default(#20073,#10000,7,14,7,40) +hasLocation(#20072,#20073) +#20074=* +tokeninfo(#20074,8,#20001,28,";") +#20075=@"loc,{#10000},7,41,7,41" +locations_default(#20075,#10000,7,41,7,41) +hasLocation(#20074,#20075) +#20076=* +tokeninfo(#20076,0,#20001,29,"") +#20077=@"loc,{#10000},8,1,8,0" +locations_default(#20077,#10000,8,1,8,0) +hasLocation(#20076,#20077) +next_token(#20002,#20076) +toplevels(#20001,0) +#20078=@"loc,{#10000},1,1,8,0" +locations_default(#20078,#10000,1,1,8,0) +hasLocation(#20001,#20078) +#20079=@"var;{data1};{#20000}" +variables(#20079,"data1",#20000) +#20080=@"var;{data2};{#20000}" +variables(#20080,"data2",#20000) +#20081=@"var;{string};{#20000}" +variables(#20081,"string",#20000) +#20082=* +stmts(#20082,23,#20001,0,"let dat ... ta1 %>;") +hasLocation(#20082,#20005) +stmt_containers(#20082,#20001) +#20083=* +exprs(#20083,64,#20082,0,"data1 = ... ata1 %>") +#20084=@"loc,{#10000},1,5,1,29" +locations_default(#20084,#10000,1,5,1,29) +hasLocation(#20083,#20084) +enclosing_stmt(#20083,#20082) +expr_containers(#20083,#20001) +#20085=* +exprs(#20085,78,#20083,0,"data1") +hasLocation(#20085,#20021) +enclosing_stmt(#20085,#20082) +expr_containers(#20085,#20001) +literals("data1","data1",#20085) +decl(#20085,#20079) +#20086=* +exprs(#20086,120,#20083,1,"<%= user_data1 %>") +#20087=@"loc,{#10000},1,13,1,29" +locations_default(#20087,#10000,1,13,1,29) +hasLocation(#20086,#20087) +enclosing_stmt(#20086,#20082) +expr_containers(#20086,#20001) +generated_code_expr_info(#20086,"<%=","%>"," user_data1 ") +#20088=* +stmts(#20088,23,#20001,1,"let dat ... ta2 %>;") +hasLocation(#20088,#20007) +stmt_containers(#20088,#20001) +#20089=* +exprs(#20089,64,#20088,0,"data2 = ... ata2 %>") +#20090=@"loc,{#10000},2,5,2,29" +locations_default(#20090,#10000,2,5,2,29) +hasLocation(#20089,#20090) +enclosing_stmt(#20089,#20088) +expr_containers(#20089,#20001) +#20091=* +exprs(#20091,78,#20089,0,"data2") +hasLocation(#20091,#20031) +enclosing_stmt(#20091,#20088) +expr_containers(#20091,#20001) +literals("data2","data2",#20091) +decl(#20091,#20080) +#20092=* +exprs(#20092,120,#20089,1,"<%- user_data2 %>") +#20093=@"loc,{#10000},2,13,2,29" +locations_default(#20093,#10000,2,13,2,29) +hasLocation(#20092,#20093) +enclosing_stmt(#20092,#20088) +expr_containers(#20092,#20001) +generated_code_expr_info(#20092,"<%-","%>"," user_data2 ") +#20094=* +stmts(#20094,3,#20001,2,"if (<%s ... g%>) {}") +hasLocation(#20094,#20009) +stmt_containers(#20094,#20001) +#20095=* +exprs(#20095,120,#20094,0,"<%something%>") +#20096=@"loc,{#10000},3,5,3,17" +locations_default(#20096,#10000,3,5,3,17) +hasLocation(#20095,#20096) +enclosing_stmt(#20095,#20094) +expr_containers(#20095,#20001) +generated_code_expr_info(#20095,"<%","%>","something") +#20097=* +stmts(#20097,1,#20094,1,"{}") +#20098=@"loc,{#10000},3,20,3,21" +locations_default(#20098,#10000,3,20,3,21) +hasLocation(#20097,#20098) +stmt_containers(#20097,#20001) +#20099=* +stmts(#20099,2,#20001,3,"foo(<%b ... baz%>);") +hasLocation(#20099,#20011) +stmt_containers(#20099,#20001) +#20100=* +exprs(#20100,13,#20099,0,"foo(<%b ... %baz%>)") +#20101=@"loc,{#10000},4,1,4,21" +locations_default(#20101,#10000,4,1,4,21) +hasLocation(#20100,#20101) +enclosing_stmt(#20100,#20099) +expr_containers(#20100,#20001) +#20102=* +exprs(#20102,79,#20100,-1,"foo") +hasLocation(#20102,#20051) +enclosing_stmt(#20102,#20099) +expr_containers(#20102,#20001) +literals("foo","foo",#20102) +#20103=@"var;{foo};{#20000}" +variables(#20103,"foo",#20000) +bind(#20102,#20103) +#20104=* +exprs(#20104,120,#20100,0,"<%bar%>") +#20105=@"loc,{#10000},4,5,4,11" +locations_default(#20105,#10000,4,5,4,11) +hasLocation(#20104,#20105) +enclosing_stmt(#20104,#20099) +expr_containers(#20104,#20001) +generated_code_expr_info(#20104,"<%","%>","bar") +#20106=* +exprs(#20106,120,#20100,1,"<%baz%>") +#20107=@"loc,{#10000},4,14,4,20" +locations_default(#20107,#10000,4,14,4,20) +hasLocation(#20106,#20107) +enclosing_stmt(#20106,#20099) +expr_containers(#20106,#20001) +generated_code_expr_info(#20106,"<%","%>","baz") +#20108=* +stmts(#20108,2,#20001,4,"<% generated_code %>") +hasLocation(#20108,#20015) +stmt_containers(#20108,#20001) +#20109=* +exprs(#20109,120,#20108,0,"<% generated_code %>") +hasLocation(#20109,#20015) +enclosing_stmt(#20109,#20108) +expr_containers(#20109,#20001) +generated_code_expr_info(#20109,"<%","%>"," generated_code ") +#20110=* +stmts(#20110,23,#20001,5,"let str ... de %>"";") +#20111=@"loc,{#10000},7,1,7,41" +locations_default(#20111,#10000,7,1,7,41) +hasLocation(#20110,#20111) +stmt_containers(#20110,#20001) +#20112=* +exprs(#20112,64,#20110,0,"string ... ode %>""") +#20113=@"loc,{#10000},7,5,7,40" +locations_default(#20113,#10000,7,5,7,40) +hasLocation(#20112,#20113) +enclosing_stmt(#20112,#20110) +expr_containers(#20112,#20001) +#20114=* +exprs(#20114,78,#20112,0,"string") +hasLocation(#20114,#20069) +enclosing_stmt(#20114,#20110) +expr_containers(#20114,#20001) +literals("string","string",#20114) +decl(#20114,#20081) +#20115=* +exprs(#20115,4,#20112,1,"""<%= no ... ode %>""") +hasLocation(#20115,#20073) +enclosing_stmt(#20115,#20110) +expr_containers(#20115,#20001) +literals("<%= not_generated_code %>","""<%= not_generated_code %>""",#20115) +#20116=* +regexpterm(#20116,14,#20115,0,"<%= not_generated_code %>") +#20117=@"loc,{#10000},7,15,7,39" +locations_default(#20117,#10000,7,15,7,39) +hasLocation(#20116,#20117) +regexp_const_value(#20116,"<%= not_generated_code %>") +#20118=* +entry_cfg_node(#20118,#20001) +#20119=@"loc,{#10000},1,1,1,0" +locations_default(#20119,#10000,1,1,1,0) +hasLocation(#20118,#20119) +#20120=* +exit_cfg_node(#20120,#20001) +hasLocation(#20120,#20077) +successor(#20110,#20114) +successor(#20115,#20112) +successor(#20114,#20115) +successor(#20112,#20120) +successor(#20108,#20109) +successor(#20109,#20110) +successor(#20099,#20102) +successor(#20106,#20100) +successor(#20104,#20106) +successor(#20102,#20104) +successor(#20100,#20108) +successor(#20094,#20095) +#20121=* +guard_node(#20121,1,#20095) +hasLocation(#20121,#20096) +successor(#20121,#20097) +#20122=* +guard_node(#20122,0,#20095) +hasLocation(#20122,#20096) +successor(#20122,#20099) +successor(#20095,#20121) +successor(#20095,#20122) +successor(#20097,#20099) +successor(#20088,#20091) +successor(#20092,#20089) +successor(#20091,#20092) +successor(#20089,#20094) +successor(#20082,#20085) +successor(#20086,#20083) +successor(#20085,#20086) +successor(#20083,#20088) +successor(#20118,#20082) +numlines(#10000,7,6,1) +filetype(#10000,"javascript") From 96a2c3f2db84703d32607a3db39d3df6f27ebaa0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 14 Jul 2021 17:53:13 +0200 Subject: [PATCH 171/429] JS: Extract .hbs and .ejs as HTML --- .../extractor/src/com/semmle/js/extractor/FileExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index ff93b671cb0..5041afa21ba 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -104,7 +104,7 @@ public class FileExtractor { /** Information about supported file types. */ public static enum FileType { - HTML(".htm", ".html", ".xhtm", ".xhtml", ".vue") { + HTML(".htm", ".html", ".xhtm", ".xhtml", ".vue", ".hbs", ".ejs") { @Override public IExtractor mkExtractor(ExtractorConfig config, ExtractorState state) { return new HTMLExtractor(config, state); From b1ce3d1c5a9f2be5e2322297cd870d8239a930ff Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 14 Jul 2021 17:53:25 +0200 Subject: [PATCH 172/429] JS: Do not extract binary HTML --- .../semmle/js/extractor/FileExtractor.java | 63 ++++++++++--------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index 5041afa21ba..5ee5061fa10 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -114,6 +114,14 @@ public class FileExtractor { public String toString() { return "html"; } + + @Override + protected boolean contains(File f, String lcExt, ExtractorConfig config) { + if (isBinaryFile(f, lcExt, config)) { + return false; + } + return super.contains(f, lcExt, config); + } }, JS(".js", ".jsx", ".mjs", ".cjs", ".es6", ".es") { @@ -152,32 +160,6 @@ public class FileExtractor { public String toString() { return "javascript"; } - - /** Number of bytes to read from the beginning of a ".js" file to detect if it is a binary file. */ - private static final int fileHeaderSize = 128; - - /** Computes if `f` is a binary file based on whether the initial `fileHeaderSize` bytes are printable UTF-8 chars. */ - private boolean isBinaryFile(File f, String lcExt, ExtractorConfig config) { - if (!config.getDefaultEncoding().equals(StandardCharsets.UTF_8.name())) { - return false; - } - try (FileInputStream fis = new FileInputStream(f)) { - byte[] bytes = new byte[fileHeaderSize]; - int length = fis.read(bytes); - - if (length == -1) return false; - - // Avoid invalid or unprintable UTF-8 files. - if (hasUnprintableUtf8(bytes, length)) { - return true; - } - - return false; - } catch (IOException e) { - Exceptions.ignore(e, "Let extractor handle this one."); - } - return false; - } }, JSON(".json") { @@ -234,9 +216,6 @@ public class FileExtractor { return super.contains(f, lcExt, config); } - /** Number of bytes to read from the beginning of a ".ts" file for sniffing its file type. */ - private static final int fileHeaderSize = 128; - private boolean hasBadFileHeader(File f, String lcExt, ExtractorConfig config) { if (!".ts".equals(lcExt)) { return false; @@ -348,6 +327,9 @@ public class FileExtractor { } }; + /** Number of bytes to read from the beginning of a file to sniff its file type. */ + private static final int fileHeaderSize = 128; + /** The file extensions (lower-case, including leading dot) corresponding to this file type. */ private final Set extensions = new LinkedHashSet(); @@ -398,6 +380,29 @@ public class FileExtractor { return true; } + /** Computes if `f` is a binary file based on whether the initial `fileHeaderSize` bytes are printable UTF-8 chars. */ + public static boolean isBinaryFile(File f, String lcExt, ExtractorConfig config) { + if (!config.getDefaultEncoding().equals(StandardCharsets.UTF_8.name())) { + return false; + } + try (FileInputStream fis = new FileInputStream(f)) { + byte[] bytes = new byte[fileHeaderSize]; + int length = fis.read(bytes); + + if (length == -1) return false; + + // Avoid invalid or unprintable UTF-8 files. + if (hasUnprintableUtf8(bytes, length)) { + return true; + } + + return false; + } catch (IOException e) { + Exceptions.ignore(e, "Let extractor handle this one."); + } + return false; + } + /** The names of all defined {@linkplain FileType}s. */ public static final Set allNames = new LinkedHashSet(); From a55a32f50acef62e67b51e0c937c6632728488be Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 9 Aug 2021 17:14:29 +0100 Subject: [PATCH 173/429] Add more missing models And corresponding tests --- .../java/frameworks/apache/Collections.qll | 3 +++ .../frameworks/apache-collections/Test.java | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 85a40ebfe59..d0f631f4d2b 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -42,6 +42,7 @@ private class ApacheCollectionsModel extends SummaryModelCsv { ";ArrayStack;true;peek;;;Element of Argument[-1];ReturnValue;value", ";ArrayStack;true;pop;;;Element of Argument[-1];ReturnValue;value", ";ArrayStack;true;push;;;Argument[0];Element of Argument[-1];value", + ";ArrayStack;true;push;;;Argument[0];ReturnValue;value", ";Bag;true;add;;;Argument[0];Element of Argument[-1];value", ";Bag;true;uniqueSet;;;Element of Argument[-1];Element of ReturnValue;value", ";BidiMap;true;getKey;;;MapKey of Argument[-1];ReturnValue;value", @@ -100,6 +101,8 @@ private class ApacheCollectionsModel extends SummaryModelCsv { ";MultiSet;true;entrySet;;;Element of Argument[-1];Element of Element of ReturnValue;value", ";MultiValuedMap;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value", ";MultiValuedMap;true;asMap;;;Element of MapValue of Argument[-1];Element of MapValue of ReturnValue;value", + ";MultiValuedMap;true;entries;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value", + ";MultiValuedMap;true;entries;;;Element of MapValue of Argument[-1];MapValue of Element of ReturnValue;value", ";MultiValuedMap;true;get;;;Element of MapValue of Argument[-1];Element of ReturnValue;value", ";MultiValuedMap;true;keys;;;MapKey of Argument[-1];Element of ReturnValue;value", ";MultiValuedMap;true;keySet;;;MapKey of Argument[-1];Element of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 20559441e51..47a386f4316 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -1087,6 +1087,14 @@ public class Test { out.push(in); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;ArrayStack;true;push;;;Argument[0];ReturnValue;value" + Object out = null; + Object in = source(); + ArrayStack instance = null; + out = instance.push(in); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;Bag;true;add;;;Argument[0];Element of Argument[-1];value" Bag out = null; @@ -2913,6 +2921,20 @@ public class Test { out = MultiMapUtils.emptyIfNull(in); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;MultiValuedMap;true;entries;;;MapKey of Argument[-1];MapKey of Element of ReturnValue;value" + Collection out = null; + MultiValuedMap in = newALVHMWithMapKey((String)source()); + out = in.entries(); + sink(getMapKeyFromEntry(getElement(out))); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;MultiValuedMap;true;entries;;;Element of MapValue of Argument[-1];MapValue of Element of ReturnValue;value" + Collection out = null; + MultiValuedMap in = newALVHMWithMapValue((String)source()); + out = in.entries(); + sink(getMapValueFromEntry(getElement(out))); // $ hasValueFlow + } { // "org.apache.commons.collections4;MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value" Collection out = null; From 200098550987a3cdd0887036bf0b548a170009ee Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 10 Aug 2021 11:58:28 +0100 Subject: [PATCH 174/429] Remove duplicate test --- .../library-tests/frameworks/apache-collections/Test.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index 47a386f4316..a88091f082e 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -238,13 +238,6 @@ public class Test { out = in.mySetKey(null); sink(out); // $ hasValueFlow } - { - // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" - Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); - out = in.mySetKey((Object)null); - sink(out); // $ hasValueFlow - } { // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value" UnmodifiableMapEntry out = null; From 51661bfa62909758c52d4c3bc81141b861257033 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 10 Aug 2021 13:24:30 +0200 Subject: [PATCH 175/429] Add pragma noinline to fix uselessUpcast check --- csharp/ql/src/semmle/code/csharp/Callable.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/csharp/ql/src/semmle/code/csharp/Callable.qll b/csharp/ql/src/semmle/code/csharp/Callable.qll index 111702bac48..a321e9356d6 100644 --- a/csharp/ql/src/semmle/code/csharp/Callable.qll +++ b/csharp/ql/src/semmle/code/csharp/Callable.qll @@ -313,6 +313,7 @@ class ExtensionMethod extends Method { override predicate isStatic() { any() } /** Gets the type being extended by this method. */ + pragma[noinline] Type getExtendedType() { result = getParameter(0).getType() } override string getAPrimaryQlClass() { result = "ExtensionMethod" } From 243424063a159ce0d1b3583b6b03171a07fe6c45 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 10 Aug 2021 13:25:56 +0200 Subject: [PATCH 176/429] Add pragma inline to getMember/Method/Callable --- csharp/ql/src/semmle/code/csharp/Type.qll | 28 ++++++++++------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index e6eabeafc59..4f464722f48 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -170,6 +170,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * } * ``` */ + pragma[inline] predicate hasMethod(Method m) { this.hasMember(m) } /** @@ -196,6 +197,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * } * ``` */ + pragma[inline] predicate hasCallable(Callable c) { hasMethod(c) or @@ -225,25 +227,15 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * } * ``` */ + pragma[inline] predicate hasMember(Member m) { - // For performance reasons, split up into "cheap" computation - // (non-overridden members) and "expensive" computation - // (overridden members). The latter is cached, and generally - // much smaller than the full relation. - hasNonOverriddenMember(m) + m = this.getAMember() + or + hasNonOverriddenMember(this.getBaseClass+(), m) or hasOverriddenMember(m) } - private predicate hasNonOverriddenMember(Member m) { - isNonOverridden(m) and - ( - m = getAMember() - or - getBaseClass+().getAMember() = m and not m.isPrivate() - ) - } - cached private predicate hasOverriddenMember(Virtualizable v) { v.isOverridden() and @@ -722,8 +714,12 @@ class RefType extends ValueOrRefType, @ref_type { override predicate isRefType() { any() } } -// Helper predicate to avoid slow "negation_body" -private predicate isNonOverridden(Member m) { not m.(Virtualizable).isOverridden() } +pragma[noinline] +private predicate hasNonOverriddenMember(Class c, Member m) { + m = c.getAMember() and + not m.(Virtualizable).isOverridden() and + not m.isPrivate() +} /** * A `class`, for example From 207c753f6fc004be133a9e8d0398d42d04ebc32b Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Tue, 10 Aug 2021 15:05:02 +0100 Subject: [PATCH 177/429] Update model for getAll --- java/ql/src/semmle/code/java/frameworks/guava/Cache.qll | 2 +- .../frameworks/guava/generated/cache/Test.java | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll index 4134158a975..f995ce63fc2 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll @@ -21,7 +21,7 @@ private class GuavaBaseCsv extends SummaryModelCsv { "com.google.common.cache;LoadingCache;true;get;(Object);;MapValue of Argument[-1];ReturnValue;value", "com.google.common.cache;LoadingCache;true;getUnchecked;(Object);;MapValue of Argument[-1];ReturnValue;value", "com.google.common.cache;LoadingCache;true;apply;(Object);;MapValue of Argument[-1];ReturnValue;value", - "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value", + "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapKey of Argument[-1];MapKey of ReturnValue;value", // technically, an interestion between MapKey of Argument[-1] and Element of Argument[0]; but we don't model intersections. "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" ] } diff --git a/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java index ea3995a6ad1..cfd1ad8e323 100644 --- a/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java +++ b/java/ql/test/library-tests/frameworks/guava/generated/cache/Test.java @@ -139,11 +139,10 @@ public class Test { sink(out); // $ hasValueFlow } { - // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value" + // "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapKey of Argument[-1];MapKey of ReturnValue;value" ImmutableMap out = null; - Iterable in = newWithElement(source()); - LoadingCache instance = null; - out = instance.getAll(in); + LoadingCache in = newCacheWithMapKey(source()); + out = in.getAll(null); sink(getMapKey(out)); // $ hasValueFlow } { From 8666bc18949014ae5eafec0a18e248096011e506 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 20 Jul 2021 10:33:54 +0200 Subject: [PATCH 178/429] JS: Extract placeholders in HTML --- .../semmle/js/extractor/HTMLExtractor.java | 118 ++- .../tests/generatedcode/input/test.html | 14 + .../generatedcode/output/trap/test.html.trap | 775 ++++++++++++++++++ javascript/ql/src/semmle/javascript/Expr.qll | 15 +- .../semmle/javascript/dataflow/DataFlow.qll | 16 + .../dataflow/internal/DataFlowNode.qll | 3 +- .../javascript/frameworks/Templating.qll | 19 + .../ql/src/semmlecode.javascript.dbscheme | 13 +- 8 files changed, 948 insertions(+), 25 deletions(-) create mode 100644 javascript/extractor/tests/generatedcode/input/test.html create mode 100644 javascript/extractor/tests/generatedcode/output/trap/test.html.trap diff --git a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java index 0e6cd756433..4c6dfc97285 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/HTMLExtractor.java @@ -81,8 +81,7 @@ public class HTMLExtractor implements IExtractor { source, content.getBegin(), isTypeScript, - elt, - context); + context.getNodeLabel(elt)); } } } else { @@ -93,6 +92,14 @@ public class HTMLExtractor implements IExtractor { // ignore empty attributes if (attr.getValue() == null || attr.getValue().isEmpty()) continue; + extractTemplateTags( + textualExtractor, + scopeManager, + attr.getSource(), + attr.getBegin(), + attr.getEnd(), + () -> context.getNodeLabel(attr)); + String source = attr.getValue(); int valueStart = attr.getValueSegment().getBegin(); if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) { @@ -104,8 +111,7 @@ public class HTMLExtractor implements IExtractor { source, valueStart, false /* isTypeScript */, - attr, - context); + context.getNodeLabel(attr)); } else if (isAngularTemplateAttributeName(attr.getName())) { // For an attribute *ngFor="let var of EXPR", start parsing at EXPR int offset = 0; @@ -125,8 +131,7 @@ public class HTMLExtractor implements IExtractor { source, valueStart + offset, false /* isTypeScript */, - attr, - context); + context.getNodeLabel(attr)); } else if (source.startsWith("javascript:")) { source = source.substring(11); extractSnippet( @@ -137,13 +142,19 @@ public class HTMLExtractor implements IExtractor { source, valueStart + 11, false /* isTypeScript */, - attr, - context); + context.getNodeLabel(attr)); } } } } + @Override + public void handleText( + Source src, int textBegin, int textEnd, Label parentLabel, boolean isCData) { + extractTemplateTags( + textualExtractor, scopeManager, src, textBegin, textEnd, () -> parentLabel); + } + @Override public boolean shouldExtractAttributes(Element element) { Attributes attributes = element.getAttributes(); @@ -294,8 +305,7 @@ public class HTMLExtractor implements IExtractor { String source, int offset, boolean isTypeScript, - Segment parentHtmlNode, - HtmlPopulator.Context context) { + Label parentLabel) { TrapWriter trapWriter = textualExtractor.getTrapwriter(); LocationManager locationManager = textualExtractor.getLocationManager(); // JavaScript AST extraction does not currently support source maps, so just set @@ -330,7 +340,7 @@ public class HTMLExtractor implements IExtractor { scriptLocationManager.getFileLabel(), scriptLocationManager.getStartLine(), scriptLocationManager.getStartColumn()); - emitTopLevelXmlNodeBinding(parentHtmlNode, topLevelLabel, context, trapWriter); + emitTopLevelXmlNodeBinding(parentLabel, topLevelLabel, trapWriter); // Note: LoC info is accounted for later, so not added here. return; } @@ -347,7 +357,7 @@ public class HTMLExtractor implements IExtractor { Pair result = extractor.extract(tx, source, toplevelKind, scopeManager); Label toplevelLabel = result.fst(); if (toplevelLabel != null) { // can be null when script ends up being parsed as JSON - emitTopLevelXmlNodeBinding(parentHtmlNode, toplevelLabel, context, trapWriter); + emitTopLevelXmlNodeBinding(parentLabel, toplevelLabel, trapWriter); } locInfo.add(result.snd()); } catch (ParseError e) { @@ -356,8 +366,88 @@ public class HTMLExtractor implements IExtractor { } } - private void emitTopLevelXmlNodeBinding(Segment parentHtmlNode, Label topLevelLabel, HtmlPopulator.Context context, TrapWriter writer) { - Label htmlNodeLabel = context.getNodeLabel(parentHtmlNode); + private void emitTopLevelXmlNodeBinding( + Label htmlNodeLabel, Label topLevelLabel, TrapWriter writer) { writer.addTuple("toplevel_parent_xml_node", topLevelLabel, htmlNodeLabel); } + + private static final String MUSTACHE_TAG_DOUBLE = "\\{\\{(?!\\{)(.*?)\\}\\}"; // {{ x }} + private static final String MUSTACHE_TAG_TRIPLE = "\\{\\{\\{(.*?)\\}\\}\\}"; // {{{ x }}} + private static final String MUSTACHE_TAG_PERCENT = "\\{%(?!>)(.*?)%\\}"; // {% x %} + private static final String EJS_TAG = "<%(?![%<>}])[-=]?(.*?)[_-]?%>"; // <% x %> + + /** Pattern for a template tag whose contents should be parsed as an expression */ + private static final Pattern TEMPLATE_EXPR_OPENING_TAG = Pattern.compile("^(?:\\{\\{\\{?|<%[-=])"); // {{, {{{, <%=, <%- + + private static final Pattern TEMPLATE_TAGS = + Pattern.compile( + StringUtil.glue( + "|", MUSTACHE_TAG_DOUBLE, MUSTACHE_TAG_TRIPLE, MUSTACHE_TAG_PERCENT, EJS_TAG), + Pattern.DOTALL); + + private void extractTemplateTags( + TextualExtractor textualExtractor, + ScopeManager scopeManager, + Source root, + int start, + int end, + Supplier
    -@angular_template_toplevel +@template_toplevel 100 @@ -438,7 +438,15 @@ 1 -@angular_pipe_ref +@template_placeholder_tag +100 + + +@template_pipe_ref +100 + + +@generated_code_expr 100 @@ -11658,6 +11666,295 @@ +expr_contains_template_tag_location +31 + + +expr +31 + + +location +31 + + + + +expr +location + + +12 + + +1 +2 +31 + + + + + + +location +expr + + +12 + + +1 +2 +31 + + + + + + + + +template_placeholder_tag_info +283 + + +node +283 + + +parentNode +92 + + +raw +24 + + + + +node +parentNode + + +12 + + +1 +2 +283 + + + + + + +node +raw + + +12 + + +1 +2 +283 + + + + + + +parentNode +node + + +12 + + +1 +2 +49 + + +2 +3 +4 + + +3 +4 +9 + + +5 +6 +9 + + +6 +7 +4 + + +7 +8 +13 + + +9 +11 +4 + + + + + + +parentNode +raw + + +12 + + +1 +2 +49 + + +2 +3 +4 + + +3 +4 +9 + + +4 +5 +11 + + +5 +6 +13 + + +6 +11 +6 + + + + + + +raw +node + + +12 + + +1 +2 +2 + + +2 +3 +4 + + +3 +4 +9 + + +4 +6 +2 + + +16 +17 +2 + + +20 +26 +2 + + +34 +45 +2 + + +82 +83 +1 + + + + + + +raw +parentNode + + +12 + + +1 +2 +2 + + +2 +3 +4 + + +3 +4 +9 + + +4 +6 +2 + + +16 +17 +2 + + +20 +26 +2 + + +34 +41 +2 + + +44 +45 +1 + + + + + + + + scopes id 118172 From 74505544e9c08e0c3f8bc8e1d8b9d98e689cb3a7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 3 Aug 2021 12:11:38 +0200 Subject: [PATCH 221/429] JS: Remove unused getTemplateContentNode --- .../ql/src/semmle/javascript/frameworks/Express.qll | 2 -- .../ql/src/semmle/javascript/frameworks/Fastify.qll | 2 -- .../ql/src/semmle/javascript/frameworks/Hapi.qll | 2 -- .../ql/src/semmle/javascript/frameworks/Koa.qll | 2 -- .../src/semmle/javascript/frameworks/Templating.qll | 11 ----------- 5 files changed, 19 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll index fe60b5b76d7..9b88b52d3ef 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll @@ -984,8 +984,6 @@ module Express { override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - override DataFlow::Node getTemplateContentNode() { none() } - override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } override DataFlow::SourceNode getOutput() { result = getCallback(2).getParameter(1) } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll index ab3be38a8c3..71e1fc69039 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll @@ -301,8 +301,6 @@ module Fastify { override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - override DataFlow::Node getTemplateContentNode() { none() } - override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll index 60c31b492d2..f1cf2c80da6 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll @@ -259,8 +259,6 @@ module Hapi { override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - override DataFlow::Node getTemplateContentNode() { none() } - override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll index c598fe5c029..83e7862a878 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll @@ -440,8 +440,6 @@ module Koa { override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - override DataFlow::Node getTemplateContentNode() { none() } - override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) or diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 7d87493dd5f..c27750254a3 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -192,9 +192,6 @@ module Templating { /** Gets a data flow node that refers a template file to be instantiated, if any. */ DataFlow::Node getTemplateFileNode() { result = range.getTemplateFileNode() } - /** Gets a data flow node that refers to the contents of the template to be instantiated, if any. */ - DataFlow::Node getTemplateContentNode() { result = range.getTemplateContentNode() } - /** Gets a data flow node that refers to an object whose properties become variables in the template. */ DataFlow::Node getTemplateParamsNode() { result = range.getTemplateParamsNode() } @@ -220,9 +217,6 @@ module Templating { /** Gets a data flow node that refers a template file to be instantiated, if any. */ abstract DataFlow::Node getTemplateFileNode(); - /** Gets a data flow node that refers to the contents of the template to be instantiated, if any. */ - abstract DataFlow::Node getTemplateContentNode(); - /** Gets a data flow node that refers to an object whose properties become variables in the template. */ abstract DataFlow::Node getTemplateParamsNode(); @@ -631,9 +625,6 @@ module Templating { /** Gets a data flow node that refers a template file to be instantiated, if any. */ override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - /** Gets a data flow node that refers to the contents of the template to be instantiated, if any. */ - override DataFlow::Node getTemplateContentNode() { none() } - /** Gets a data flow node that refers to an object whose properties become variables in the template. */ override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } @@ -709,8 +700,6 @@ module Templating { override DataFlow::Node getTemplateFileNode() { result = getArgument(0) } - override DataFlow::Node getTemplateContentNode() { none() } - override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } } From b9b10af9b5c4ee3062fa5d33469d94076f67630b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 5 Aug 2021 10:58:30 +0200 Subject: [PATCH 222/429] JS: Tolerate parse errors in test due to speculative parsing --- .../frameworks/AngularJS/expressions/lexing/options | 1 + .../frameworks/AngularJS/expressions/parsing/options | 1 + javascript/ql/test/query-tests/DOM/HTML/options | 2 +- javascript/ql/test/query-tests/DOM/TargetBlank/options | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/lexing/options create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/parsing/options create mode 100644 javascript/ql/test/query-tests/DOM/TargetBlank/options diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/lexing/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/lexing/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/lexing/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/parsing/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/parsing/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/parsing/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/DOM/HTML/options b/javascript/ql/test/query-tests/DOM/HTML/options index 49be7a9261e..90f53bd4e9a 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/options +++ b/javascript/ql/test/query-tests/DOM/HTML/options @@ -1 +1 @@ -semmle-extractor-options: --html elements +semmle-extractor-options: --html elements --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/DOM/TargetBlank/options b/javascript/ql/test/query-tests/DOM/TargetBlank/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/DOM/TargetBlank/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors From 13fa49a7f1629d90794839d99ce2134f8690e981 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 12:17:17 +0200 Subject: [PATCH 223/429] JS: Update TRAP output --- .../generatedcode/output/trap/ejs.js.trap | 12 +- .../generatedcode/output/trap/test.html.trap | 13 +- .../generatedcode/output/trap/tst.js.trap | 10 +- .../tests/html/output/trap/entities.html.trap | 216 ++-- .../html/output/trap/json_in_script.html.trap | 38 +- .../tests/html/output/trap/module.html.trap | 356 +++---- .../tests/html/output/trap/tst.html.trap | 932 ++++++++++-------- .../tests/html/output/trap/tst.xhtml.trap | 128 +-- .../tests/html/output/trap/tst2.html.trap | 604 ++++++------ .../output/trap/component.js.trap | 410 ++++---- .../tests/node/output/trap/tst.html.trap | 156 +-- .../tests/shebang/output/trap/tst.html.trap | 70 +- 12 files changed, 1529 insertions(+), 1416 deletions(-) diff --git a/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap b/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap index cebf13a3fda..78151c8ca2d 100644 --- a/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap +++ b/javascript/extractor/tests/generatedcode/output/trap/ejs.js.trap @@ -243,7 +243,7 @@ locations_default(#20087,#10000,1,13,1,29) hasLocation(#20086,#20087) enclosing_stmt(#20086,#20082) expr_containers(#20086,#20001) -generated_code_expr_info(#20086,"<%=","%>"," user_data1 ") +expr_contains_template_tag_location(#20086,#20087) #20088=* stmts(#20088,23,#20001,1,"let dat ... ta2 %>;") hasLocation(#20088,#20007) @@ -269,7 +269,7 @@ locations_default(#20093,#10000,2,13,2,29) hasLocation(#20092,#20093) enclosing_stmt(#20092,#20088) expr_containers(#20092,#20001) -generated_code_expr_info(#20092,"<%-","%>"," user_data2 ") +expr_contains_template_tag_location(#20092,#20093) #20094=* stmts(#20094,3,#20001,2,"if (<%s ... g%>) {}") hasLocation(#20094,#20009) @@ -281,7 +281,7 @@ locations_default(#20096,#10000,3,5,3,17) hasLocation(#20095,#20096) enclosing_stmt(#20095,#20094) expr_containers(#20095,#20001) -generated_code_expr_info(#20095,"<%","%>","something") +expr_contains_template_tag_location(#20095,#20096) #20097=* stmts(#20097,1,#20094,1,"{}") #20098=@"loc,{#10000},3,20,3,21" @@ -315,7 +315,7 @@ locations_default(#20105,#10000,4,5,4,11) hasLocation(#20104,#20105) enclosing_stmt(#20104,#20099) expr_containers(#20104,#20001) -generated_code_expr_info(#20104,"<%","%>","bar") +expr_contains_template_tag_location(#20104,#20105) #20106=* exprs(#20106,120,#20100,1,"<%baz%>") #20107=@"loc,{#10000},4,14,4,20" @@ -323,7 +323,7 @@ locations_default(#20107,#10000,4,14,4,20) hasLocation(#20106,#20107) enclosing_stmt(#20106,#20099) expr_containers(#20106,#20001) -generated_code_expr_info(#20106,"<%","%>","baz") +expr_contains_template_tag_location(#20106,#20107) #20108=* stmts(#20108,2,#20001,4,"<% generated_code %>") hasLocation(#20108,#20015) @@ -333,7 +333,7 @@ exprs(#20109,120,#20108,0,"<% generated_code %>") hasLocation(#20109,#20015) enclosing_stmt(#20109,#20108) expr_containers(#20109,#20001) -generated_code_expr_info(#20109,"<%","%>"," generated_code ") +expr_contains_template_tag_location(#20109,#20015) #20110=* stmts(#20110,23,#20001,5,"let str ... de %>"";") #20111=@"loc,{#10000},7,1,7,41" diff --git a/javascript/extractor/tests/generatedcode/output/trap/test.html.trap b/javascript/extractor/tests/generatedcode/output/trap/test.html.trap index c1783682e45..ec2f280c5e1 100644 --- a/javascript/extractor/tests/generatedcode/output/trap/test.html.trap +++ b/javascript/extractor/tests/generatedcode/output/trap/test.html.trap @@ -160,7 +160,7 @@ locations_default(#20055,#10000,9,19,9,36) hasLocation(#20054,#20055) enclosing_stmt(#20054,#20049) expr_containers(#20054,#20002) -generated_code_expr_info(#20054,"{{{","}}}"," user_data1 ") +expr_contains_template_tag_location(#20054,#20055) #20056=* stmts(#20056,18,#20002,1,"var dat ... afe }};") #20057=@"loc,{#10000},10,7,10,49" @@ -188,7 +188,7 @@ locations_default(#20062,#10000,10,19,10,48) hasLocation(#20061,#20062) enclosing_stmt(#20061,#20056) expr_containers(#20061,#20002) -generated_code_expr_info(#20061,"{{","}}"," user_data2 | json | safe ") +expr_contains_template_tag_location(#20061,#20062) #20063=* stmts(#20063,18,#20002,2,"var dat ... ta3 %>;") #20064=@"loc,{#10000},11,7,11,36" @@ -216,7 +216,7 @@ locations_default(#20069,#10000,11,19,11,35) hasLocation(#20068,#20069) enclosing_stmt(#20068,#20063) expr_containers(#20068,#20002) -generated_code_expr_info(#20068,"<%-","%>"," user_data3 ") +expr_contains_template_tag_location(#20068,#20069) #20070=* entry_cfg_node(#20070,#20002) hasLocation(#20070,#20004) @@ -276,6 +276,7 @@ template_placeholder_tag_info(#20084,#20080,"{{{subtitle_html}}}") #20085=@"loc,{#10000},5,5,5,23" locations_default(#20085,#10000,5,5,5,23) hasLocation(#20084,#20085) +scopes(#20000,0) #20086=@"script;{#10000},5,8" #20087=* lines(#20087,#20086,"subtitle_html","") @@ -356,6 +357,7 @@ xmllocations(#20001,#20107) template_placeholder_tag_info(#20108,#20001,"{{{ user_data1 }}}") locations_default(#20055,#10000,9,19,9,36) hasLocation(#20108,#20055) +scopes(#20000,0) #20109=@"script;{#10000},9,22" #20110=* lines(#20110,#20109," user_data1 ","") @@ -410,6 +412,7 @@ toplevel_parent_xml_node(#20109,#20108) template_placeholder_tag_info(#20123,#20001,"{{ user_data2 | json | safe }}") locations_default(#20062,#10000,10,19,10,48) hasLocation(#20123,#20062) +scopes(#20000,0) #20124=@"script;{#10000},10,21" #20125=* lines(#20125,#20124," user_data2 | json | safe ","") @@ -524,6 +527,7 @@ toplevel_parent_xml_node(#20124,#20123) template_placeholder_tag_info(#20154,#20001,"<%- user_data3 %>") locations_default(#20069,#10000,11,19,11,35) hasLocation(#20154,#20069) +scopes(#20000,0) #20155=@"script;{#10000},11,22" #20156=* lines(#20156,#20155," user_data3 ","") @@ -592,6 +596,7 @@ template_placeholder_tag_info(#20172,#20170,"<%= footer %>") #20173=@"loc,{#10000},7,8,7,20" locations_default(#20173,#10000,7,8,7,20) hasLocation(#20172,#20173) +scopes(#20000,0) #20174=@"script;{#10000},7,11" #20175=* lines(#20175,#20174," footer ","") @@ -656,6 +661,7 @@ template_placeholder_tag_info(#20191,#20189,"<%- body_html %>") #20192=@"loc,{#10000},6,8,6,23" locations_default(#20192,#10000,6,8,6,23) hasLocation(#20191,#20192) +scopes(#20000,0) #20193=@"script;{#10000},6,11" #20194=* lines(#20194,#20193," body_html ","") @@ -720,6 +726,7 @@ template_placeholder_tag_info(#20210,#20208,"{{title}}") #20211=@"loc,{#10000},4,9,4,17" locations_default(#20211,#10000,4,9,4,17) hasLocation(#20210,#20211) +scopes(#20000,0) #20212=@"script;{#10000},4,11" #20213=* lines(#20213,#20212,"title","") diff --git a/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap b/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap index c1293cb897b..852d0001206 100644 --- a/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap +++ b/javascript/extractor/tests/generatedcode/output/trap/tst.js.trap @@ -398,7 +398,7 @@ locations_default(#20147,#10000,1,13,1,28) hasLocation(#20146,#20147) enclosing_stmt(#20146,#20142) expr_containers(#20146,#20001) -generated_code_expr_info(#20146,"{{","}}"," user_data1 ") +expr_contains_template_tag_location(#20146,#20147) #20148=* stmts(#20148,23,#20001,1,"let dat ... a2 }}};") hasLocation(#20148,#20013) @@ -424,7 +424,7 @@ locations_default(#20153,#10000,2,13,2,30) hasLocation(#20152,#20153) enclosing_stmt(#20152,#20148) expr_containers(#20152,#20001) -generated_code_expr_info(#20152,"{{{","}}}"," user_data2 ") +expr_contains_template_tag_location(#20152,#20153) #20154=* stmts(#20154,3,#20001,2,"if ({{s ... g}}) {}") hasLocation(#20154,#20015) @@ -436,7 +436,7 @@ locations_default(#20156,#10000,3,5,3,17) hasLocation(#20155,#20156) enclosing_stmt(#20155,#20154) expr_containers(#20155,#20001) -generated_code_expr_info(#20155,"{{","}}","something") +expr_contains_template_tag_location(#20155,#20156) #20157=* stmts(#20157,1,#20154,1,"{}") #20158=@"loc,{#10000},3,20,3,21" @@ -470,7 +470,7 @@ locations_default(#20165,#10000,4,5,4,11) hasLocation(#20164,#20165) enclosing_stmt(#20164,#20159) expr_containers(#20164,#20001) -generated_code_expr_info(#20164,"{{","}}","bar") +expr_contains_template_tag_location(#20164,#20165) #20166=* exprs(#20166,120,#20160,1,"{{baz}}") #20167=@"loc,{#10000},4,14,4,20" @@ -478,7 +478,7 @@ locations_default(#20167,#10000,4,14,4,20) hasLocation(#20166,#20167) enclosing_stmt(#20166,#20159) expr_containers(#20166,#20001) -generated_code_expr_info(#20166,"{{","}}","baz") +expr_contains_template_tag_location(#20166,#20167) #20168=* stmts(#20168,1,#20001,4,"{{not_g ... _code}}") #20169=@"loc,{#10000},6,1,6,22" diff --git a/javascript/extractor/tests/html/output/trap/entities.html.trap b/javascript/extractor/tests/html/output/trap/entities.html.trap index 66c12b952a4..217c18f7378 100644 --- a/javascript/extractor/tests/html/output/trap/entities.html.trap +++ b/javascript/extractor/tests/html/output/trap/entities.html.trap @@ -8,116 +8,116 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},6,29" -#20002=* -lines(#20002,#20001,"void(alert(""Nope!""))","") -#20003=@"loc,{#10000},6,29,6,48" -locations_default(#20003,#10000,6,29,6,48) -hasLocation(#20002,#20003) -numlines(#20001,1,1,0) -#20004=* -tokeninfo(#20004,7,#20001,0,"void") -#20005=@"loc,{#10000},6,29,6,32" -locations_default(#20005,#10000,6,29,6,32) -hasLocation(#20004,#20005) -#20006=* -tokeninfo(#20006,8,#20001,1,"(") -#20007=@"loc,{#10000},6,33,6,33" -locations_default(#20007,#10000,6,33,6,33) -hasLocation(#20006,#20007) -#20008=* -tokeninfo(#20008,6,#20001,2,"alert") -#20009=@"loc,{#10000},6,34,6,38" -locations_default(#20009,#10000,6,34,6,38) -hasLocation(#20008,#20009) -#20010=* -tokeninfo(#20010,8,#20001,3,"(") -#20011=@"loc,{#10000},6,39,6,39" -locations_default(#20011,#10000,6,39,6,39) -hasLocation(#20010,#20011) -#20012=* -tokeninfo(#20012,4,#20001,4,"""Nope!""") -#20013=@"loc,{#10000},6,40,6,46" -locations_default(#20013,#10000,6,40,6,46) -hasLocation(#20012,#20013) -#20014=* -tokeninfo(#20014,8,#20001,5,")") -#20015=@"loc,{#10000},6,47,6,47" -locations_default(#20015,#10000,6,47,6,47) -hasLocation(#20014,#20015) -#20016=* -tokeninfo(#20016,8,#20001,6,")") -#20017=@"loc,{#10000},6,48,6,48" -locations_default(#20017,#10000,6,48,6,48) -hasLocation(#20016,#20017) -#20018=* -tokeninfo(#20018,0,#20001,7,"") -#20019=@"loc,{#10000},6,49,6,48" -locations_default(#20019,#10000,6,49,6,48) -hasLocation(#20018,#20019) -toplevels(#20001,3) -hasLocation(#20001,#20003) -#20020=* -stmts(#20020,2,#20001,0,"void(alert(""Nope!""))") -hasLocation(#20020,#20003) -stmt_containers(#20020,#20001) +#20001=* +#20002=@"script;{#10000},6,29" +#20003=* +lines(#20003,#20002,"void(alert(""Nope!""))","") +#20004=@"loc,{#10000},6,29,6,48" +locations_default(#20004,#10000,6,29,6,48) +hasLocation(#20003,#20004) +numlines(#20002,1,1,0) +#20005=* +tokeninfo(#20005,7,#20002,0,"void") +#20006=@"loc,{#10000},6,29,6,32" +locations_default(#20006,#10000,6,29,6,32) +hasLocation(#20005,#20006) +#20007=* +tokeninfo(#20007,8,#20002,1,"(") +#20008=@"loc,{#10000},6,33,6,33" +locations_default(#20008,#10000,6,33,6,33) +hasLocation(#20007,#20008) +#20009=* +tokeninfo(#20009,6,#20002,2,"alert") +#20010=@"loc,{#10000},6,34,6,38" +locations_default(#20010,#10000,6,34,6,38) +hasLocation(#20009,#20010) +#20011=* +tokeninfo(#20011,8,#20002,3,"(") +#20012=@"loc,{#10000},6,39,6,39" +locations_default(#20012,#10000,6,39,6,39) +hasLocation(#20011,#20012) +#20013=* +tokeninfo(#20013,4,#20002,4,"""Nope!""") +#20014=@"loc,{#10000},6,40,6,46" +locations_default(#20014,#10000,6,40,6,46) +hasLocation(#20013,#20014) +#20015=* +tokeninfo(#20015,8,#20002,5,")") +#20016=@"loc,{#10000},6,47,6,47" +locations_default(#20016,#10000,6,47,6,47) +hasLocation(#20015,#20016) +#20017=* +tokeninfo(#20017,8,#20002,6,")") +#20018=@"loc,{#10000},6,48,6,48" +locations_default(#20018,#10000,6,48,6,48) +hasLocation(#20017,#20018) +#20019=* +tokeninfo(#20019,0,#20002,7,"") +#20020=@"loc,{#10000},6,49,6,48" +locations_default(#20020,#10000,6,49,6,48) +hasLocation(#20019,#20020) +toplevels(#20002,3) +hasLocation(#20002,#20004) #20021=* -exprs(#20021,21,#20020,0,"void(alert(""Nope!""))") -hasLocation(#20021,#20003) -enclosing_stmt(#20021,#20020) -expr_containers(#20021,#20001) +stmts(#20021,2,#20002,0,"void(alert(""Nope!""))") +hasLocation(#20021,#20004) +stmt_containers(#20021,#20002) #20022=* -exprs(#20022,63,#20021,0,"(alert(""Nope!""))") -#20023=@"loc,{#10000},6,33,6,48" -locations_default(#20023,#10000,6,33,6,48) -hasLocation(#20022,#20023) -enclosing_stmt(#20022,#20020) -expr_containers(#20022,#20001) -#20024=* -exprs(#20024,13,#20022,0,"alert(""Nope!"")") -#20025=@"loc,{#10000},6,34,6,47" -locations_default(#20025,#10000,6,34,6,47) -hasLocation(#20024,#20025) -enclosing_stmt(#20024,#20020) -expr_containers(#20024,#20001) -#20026=* -exprs(#20026,79,#20024,-1,"alert") -hasLocation(#20026,#20009) -enclosing_stmt(#20026,#20020) -expr_containers(#20026,#20001) -literals("alert","alert",#20026) -#20027=@"var;{alert};{#20000}" -variables(#20027,"alert",#20000) -bind(#20026,#20027) -#20028=* -exprs(#20028,4,#20024,0,"""Nope!""") -hasLocation(#20028,#20013) -enclosing_stmt(#20028,#20020) -expr_containers(#20028,#20001) -literals("Nope!","""Nope!""",#20028) +exprs(#20022,21,#20021,0,"void(alert(""Nope!""))") +hasLocation(#20022,#20004) +enclosing_stmt(#20022,#20021) +expr_containers(#20022,#20002) +#20023=* +exprs(#20023,63,#20022,0,"(alert(""Nope!""))") +#20024=@"loc,{#10000},6,33,6,48" +locations_default(#20024,#10000,6,33,6,48) +hasLocation(#20023,#20024) +enclosing_stmt(#20023,#20021) +expr_containers(#20023,#20002) +#20025=* +exprs(#20025,13,#20023,0,"alert(""Nope!"")") +#20026=@"loc,{#10000},6,34,6,47" +locations_default(#20026,#10000,6,34,6,47) +hasLocation(#20025,#20026) +enclosing_stmt(#20025,#20021) +expr_containers(#20025,#20002) +#20027=* +exprs(#20027,79,#20025,-1,"alert") +hasLocation(#20027,#20010) +enclosing_stmt(#20027,#20021) +expr_containers(#20027,#20002) +literals("alert","alert",#20027) +#20028=@"var;{alert};{#20000}" +variables(#20028,"alert",#20000) +bind(#20027,#20028) #20029=* -regexpterm(#20029,14,#20028,0,"Nope!") -#20030=@"loc,{#10000},6,41,6,45" -locations_default(#20030,#10000,6,41,6,45) -hasLocation(#20029,#20030) -regexp_const_value(#20029,"Nope!") -#20031=* -entry_cfg_node(#20031,#20001) -#20032=@"loc,{#10000},6,29,6,28" -locations_default(#20032,#10000,6,29,6,28) -hasLocation(#20031,#20032) -#20033=* -exit_cfg_node(#20033,#20001) -hasLocation(#20033,#20019) -successor(#20020,#20022) -successor(#20022,#20026) -successor(#20028,#20024) -successor(#20026,#20028) -successor(#20024,#20021) -successor(#20021,#20033) -successor(#20031,#20020) +exprs(#20029,4,#20025,0,"""Nope!""") +hasLocation(#20029,#20014) +enclosing_stmt(#20029,#20021) +expr_containers(#20029,#20002) +literals("Nope!","""Nope!""",#20029) +#20030=* +regexpterm(#20030,14,#20029,0,"Nope!") +#20031=@"loc,{#10000},6,41,6,45" +locations_default(#20031,#10000,6,41,6,45) +hasLocation(#20030,#20031) +regexp_const_value(#20030,"Nope!") +#20032=* +entry_cfg_node(#20032,#20002) +#20033=@"loc,{#10000},6,29,6,28" +locations_default(#20033,#10000,6,29,6,28) +hasLocation(#20032,#20033) #20034=* -toplevel_parent_xml_node(#20001,#20034) +exit_cfg_node(#20034,#20002) +hasLocation(#20034,#20020) +successor(#20021,#20023) +successor(#20023,#20027) +successor(#20029,#20025) +successor(#20027,#20029) +successor(#20025,#20022) +successor(#20022,#20034) +successor(#20032,#20021) +toplevel_parent_xml_node(#20002,#20001) #20035=* xmlElements(#20035,"html",#10000,0,#10000) #20036=@"loc,{#10000},1,1,8,7" @@ -133,10 +133,10 @@ 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) +xmlAttrs(#20001,#20039,"href","javascript:void(alert(""Nope!""))",0,#10000) #20041=@"loc,{#10000},6,12,6,65" locations_default(#20041,#10000,6,12,6,65) -xmllocations(#20034,#20041) +xmllocations(#20001,#20041) #20042=* xmlElements(#20042,"head",#20035,0,#10000) #20043=@"loc,{#10000},2,5,4,11" 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 index f7855255420..651012c8360 100644 --- a/javascript/extractor/tests/html/output/trap/json_in_script.html.trap +++ b/javascript/extractor/tests/html/output/trap/json_in_script.html.trap @@ -9,26 +9,26 @@ 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) +#20002=* +json(#20002,5,#10000,0,"{""Hello"": 123}") +#20003=@"loc,{#10000},3,1,3,14" +locations_default(#20003,#10000,3,1,3,14) +json_locations(#20002,#20003) +#20004=* +json(#20004,2,#20002,0,"123") +#20005=@"loc,{#10000},3,11,3,13" +locations_default(#20005,#10000,3,11,3,13) +json_locations(#20004,#20005) +json_literals("123","123",#20004) +json_properties(#20002,"Hello",#20004) +#20006=* +xmlElements(#20006,"html",#10000,0,#10000) +#20007=@"loc,{#10000},1,1,5,7" +locations_default(#20007,#10000,1,1,5,7) +xmllocations(#20006,#20007) +xmlElements(#20001,"script",#20006,0,#10000) #20008=@"loc,{#10000},2,1,4,9" locations_default(#20008,#10000,2,1,4,9) -xmllocations(#20007,#20008) +xmllocations(#20001,#20008) numlines(#10000,5,0,0) filetype(#10000,"html") diff --git a/javascript/extractor/tests/html/output/trap/module.html.trap b/javascript/extractor/tests/html/output/trap/module.html.trap index 3932e850cbd..4b497e2972e 100644 --- a/javascript/extractor/tests/html/output/trap/module.html.trap +++ b/javascript/extractor/tests/html/output/trap/module.html.trap @@ -8,193 +8,193 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},4,31" -#20002=* -lines(#20002,#20001,""," +#20001=* +#20002=@"script;{#10000},4,31" +#20003=* +lines(#20003,#20002,""," ") -#20003=@"loc,{#10000},4,31,4,30" -locations_default(#20003,#10000,4,31,4,30) -hasLocation(#20002,#20003) -#20004=* -lines(#20004,#20001," import foo from 'bar';"," +#20004=@"loc,{#10000},4,31,4,30" +locations_default(#20004,#10000,4,31,4,30) +hasLocation(#20003,#20004) +#20005=* +lines(#20005,#20002," import foo from 'bar';"," ") -#20005=@"loc,{#10000},5,1,5,34" -locations_default(#20005,#10000,5,1,5,34) -hasLocation(#20004,#20005) +#20006=@"loc,{#10000},5,1,5,34" +locations_default(#20006,#10000,5,1,5,34) +hasLocation(#20005,#20006) indentation(#10000,5," ",12) -#20006=* -lines(#20006,#20001," foo.baz();"," +#20007=* +lines(#20007,#20002," foo.baz();"," ") -#20007=@"loc,{#10000},6,1,6,22" -locations_default(#20007,#10000,6,1,6,22) -hasLocation(#20006,#20007) +#20008=@"loc,{#10000},6,1,6,22" +locations_default(#20008,#10000,6,1,6,22) +hasLocation(#20007,#20008) indentation(#10000,6," ",12) -#20008=* -lines(#20008,#20001," ","") -#20009=@"loc,{#10000},7,1,7,8" -locations_default(#20009,#10000,7,1,7,8) -hasLocation(#20008,#20009) -numlines(#20001,4,2,0) -#20010=* -tokeninfo(#20010,7,#20001,0,"import") -#20011=@"loc,{#10000},5,13,5,18" -locations_default(#20011,#10000,5,13,5,18) -hasLocation(#20010,#20011) -#20012=* -tokeninfo(#20012,6,#20001,1,"foo") -#20013=@"loc,{#10000},5,20,5,22" -locations_default(#20013,#10000,5,20,5,22) -hasLocation(#20012,#20013) -#20014=* -tokeninfo(#20014,6,#20001,2,"from") -#20015=@"loc,{#10000},5,24,5,27" -locations_default(#20015,#10000,5,24,5,27) -hasLocation(#20014,#20015) -#20016=* -tokeninfo(#20016,4,#20001,3,"'bar'") -#20017=@"loc,{#10000},5,29,5,33" -locations_default(#20017,#10000,5,29,5,33) -hasLocation(#20016,#20017) -#20018=* -tokeninfo(#20018,8,#20001,4,";") -#20019=@"loc,{#10000},5,34,5,34" -locations_default(#20019,#10000,5,34,5,34) -hasLocation(#20018,#20019) -#20020=* -tokeninfo(#20020,6,#20001,5,"foo") -#20021=@"loc,{#10000},6,13,6,15" -locations_default(#20021,#10000,6,13,6,15) -hasLocation(#20020,#20021) -#20022=* -tokeninfo(#20022,8,#20001,6,".") -#20023=@"loc,{#10000},6,16,6,16" -locations_default(#20023,#10000,6,16,6,16) -hasLocation(#20022,#20023) -#20024=* -tokeninfo(#20024,6,#20001,7,"baz") -#20025=@"loc,{#10000},6,17,6,19" -locations_default(#20025,#10000,6,17,6,19) -hasLocation(#20024,#20025) -#20026=* -tokeninfo(#20026,8,#20001,8,"(") -#20027=@"loc,{#10000},6,20,6,20" -locations_default(#20027,#10000,6,20,6,20) -hasLocation(#20026,#20027) -#20028=* -tokeninfo(#20028,8,#20001,9,")") -#20029=@"loc,{#10000},6,21,6,21" -locations_default(#20029,#10000,6,21,6,21) -hasLocation(#20028,#20029) -#20030=* -tokeninfo(#20030,8,#20001,10,";") -#20031=@"loc,{#10000},6,22,6,22" -locations_default(#20031,#10000,6,22,6,22) -hasLocation(#20030,#20031) -#20032=* -tokeninfo(#20032,0,#20001,11,"") -#20033=@"loc,{#10000},7,9,7,8" -locations_default(#20033,#10000,7,9,7,8) -hasLocation(#20032,#20033) -toplevels(#20001,1) -#20034=@"loc,{#10000},4,31,7,8" -locations_default(#20034,#10000,4,31,7,8) -hasLocation(#20001,#20034) -#20035=@"module;{#10000},4,31" -scopes(#20035,3) -scopenodes(#20001,#20035) -scopenesting(#20035,#20000) -is_module(#20001) -is_es2015_module(#20001) -#20036=@"var;{foo};{#20035}" -variables(#20036,"foo",#20035) -#20037=@"local_type_name;{foo};{#20035}" -local_type_names(#20037,"foo",#20035) -#20038=@"local_namespace_name;{foo};{#20035}" -local_namespace_names(#20038,"foo",#20035) -variables(#20036,"foo",#20035) -local_type_names(#20037,"foo",#20035) -local_namespace_names(#20038,"foo",#20035) -#20039=* -stmts(#20039,27,#20001,0,"import ... 'bar';") -#20040=@"loc,{#10000},5,13,5,34" -locations_default(#20040,#10000,5,13,5,34) -hasLocation(#20039,#20040) -stmt_containers(#20039,#20001) -#20041=* -exprs(#20041,4,#20039,-1,"'bar'") -hasLocation(#20041,#20017) -enclosing_stmt(#20041,#20039) -expr_containers(#20041,#20001) -literals("bar","'bar'",#20041) +#20009=* +lines(#20009,#20002," ","") +#20010=@"loc,{#10000},7,1,7,8" +locations_default(#20010,#10000,7,1,7,8) +hasLocation(#20009,#20010) +numlines(#20002,4,2,0) +#20011=* +tokeninfo(#20011,7,#20002,0,"import") +#20012=@"loc,{#10000},5,13,5,18" +locations_default(#20012,#10000,5,13,5,18) +hasLocation(#20011,#20012) +#20013=* +tokeninfo(#20013,6,#20002,1,"foo") +#20014=@"loc,{#10000},5,20,5,22" +locations_default(#20014,#10000,5,20,5,22) +hasLocation(#20013,#20014) +#20015=* +tokeninfo(#20015,6,#20002,2,"from") +#20016=@"loc,{#10000},5,24,5,27" +locations_default(#20016,#10000,5,24,5,27) +hasLocation(#20015,#20016) +#20017=* +tokeninfo(#20017,4,#20002,3,"'bar'") +#20018=@"loc,{#10000},5,29,5,33" +locations_default(#20018,#10000,5,29,5,33) +hasLocation(#20017,#20018) +#20019=* +tokeninfo(#20019,8,#20002,4,";") +#20020=@"loc,{#10000},5,34,5,34" +locations_default(#20020,#10000,5,34,5,34) +hasLocation(#20019,#20020) +#20021=* +tokeninfo(#20021,6,#20002,5,"foo") +#20022=@"loc,{#10000},6,13,6,15" +locations_default(#20022,#10000,6,13,6,15) +hasLocation(#20021,#20022) +#20023=* +tokeninfo(#20023,8,#20002,6,".") +#20024=@"loc,{#10000},6,16,6,16" +locations_default(#20024,#10000,6,16,6,16) +hasLocation(#20023,#20024) +#20025=* +tokeninfo(#20025,6,#20002,7,"baz") +#20026=@"loc,{#10000},6,17,6,19" +locations_default(#20026,#10000,6,17,6,19) +hasLocation(#20025,#20026) +#20027=* +tokeninfo(#20027,8,#20002,8,"(") +#20028=@"loc,{#10000},6,20,6,20" +locations_default(#20028,#10000,6,20,6,20) +hasLocation(#20027,#20028) +#20029=* +tokeninfo(#20029,8,#20002,9,")") +#20030=@"loc,{#10000},6,21,6,21" +locations_default(#20030,#10000,6,21,6,21) +hasLocation(#20029,#20030) +#20031=* +tokeninfo(#20031,8,#20002,10,";") +#20032=@"loc,{#10000},6,22,6,22" +locations_default(#20032,#10000,6,22,6,22) +hasLocation(#20031,#20032) +#20033=* +tokeninfo(#20033,0,#20002,11,"") +#20034=@"loc,{#10000},7,9,7,8" +locations_default(#20034,#10000,7,9,7,8) +hasLocation(#20033,#20034) +toplevels(#20002,1) +#20035=@"loc,{#10000},4,31,7,8" +locations_default(#20035,#10000,4,31,7,8) +hasLocation(#20002,#20035) +#20036=@"module;{#10000},4,31" +scopes(#20036,3) +scopenodes(#20002,#20036) +scopenesting(#20036,#20000) +is_module(#20002) +is_es2015_module(#20002) +#20037=@"var;{foo};{#20036}" +variables(#20037,"foo",#20036) +#20038=@"local_type_name;{foo};{#20036}" +local_type_names(#20038,"foo",#20036) +#20039=@"local_namespace_name;{foo};{#20036}" +local_namespace_names(#20039,"foo",#20036) +variables(#20037,"foo",#20036) +local_type_names(#20038,"foo",#20036) +local_namespace_names(#20039,"foo",#20036) +#20040=* +stmts(#20040,27,#20002,0,"import ... 'bar';") +#20041=@"loc,{#10000},5,13,5,34" +locations_default(#20041,#10000,5,13,5,34) +hasLocation(#20040,#20041) +stmt_containers(#20040,#20002) #20042=* -regexpterm(#20042,14,#20041,0,"bar") -#20043=@"loc,{#10000},5,30,5,32" -locations_default(#20043,#10000,5,30,5,32) -hasLocation(#20042,#20043) -regexp_const_value(#20042,"bar") -#20044=* -exprs(#20044,84,#20039,0,"foo") -hasLocation(#20044,#20013) -enclosing_stmt(#20044,#20039) -expr_containers(#20044,#20001) +exprs(#20042,4,#20040,-1,"'bar'") +hasLocation(#20042,#20018) +enclosing_stmt(#20042,#20040) +expr_containers(#20042,#20002) +literals("bar","'bar'",#20042) +#20043=* +regexpterm(#20043,14,#20042,0,"bar") +#20044=@"loc,{#10000},5,30,5,32" +locations_default(#20044,#10000,5,30,5,32) +hasLocation(#20043,#20044) +regexp_const_value(#20043,"bar") #20045=* -exprs(#20045,78,#20044,1,"foo") -hasLocation(#20045,#20013) -enclosing_stmt(#20045,#20039) -expr_containers(#20045,#20001) -literals("foo","foo",#20045) -decl(#20045,#20036) -typedecl(#20045,#20037) -namespacedecl(#20045,#20038) +exprs(#20045,84,#20040,0,"foo") +hasLocation(#20045,#20014) +enclosing_stmt(#20045,#20040) +expr_containers(#20045,#20002) #20046=* -stmts(#20046,2,#20001,1,"foo.baz();") -#20047=@"loc,{#10000},6,13,6,22" -locations_default(#20047,#10000,6,13,6,22) -hasLocation(#20046,#20047) -stmt_containers(#20046,#20001) -#20048=* -exprs(#20048,13,#20046,0,"foo.baz()") -#20049=@"loc,{#10000},6,13,6,21" -locations_default(#20049,#10000,6,13,6,21) -hasLocation(#20048,#20049) -enclosing_stmt(#20048,#20046) -expr_containers(#20048,#20001) -#20050=* -exprs(#20050,14,#20048,-1,"foo.baz") -#20051=@"loc,{#10000},6,13,6,19" -locations_default(#20051,#10000,6,13,6,19) -hasLocation(#20050,#20051) -enclosing_stmt(#20050,#20046) -expr_containers(#20050,#20001) -#20052=* -exprs(#20052,79,#20050,0,"foo") -hasLocation(#20052,#20021) -enclosing_stmt(#20052,#20046) -expr_containers(#20052,#20001) -literals("foo","foo",#20052) -bind(#20052,#20036) +exprs(#20046,78,#20045,1,"foo") +hasLocation(#20046,#20014) +enclosing_stmt(#20046,#20040) +expr_containers(#20046,#20002) +literals("foo","foo",#20046) +decl(#20046,#20037) +typedecl(#20046,#20038) +namespacedecl(#20046,#20039) +#20047=* +stmts(#20047,2,#20002,1,"foo.baz();") +#20048=@"loc,{#10000},6,13,6,22" +locations_default(#20048,#10000,6,13,6,22) +hasLocation(#20047,#20048) +stmt_containers(#20047,#20002) +#20049=* +exprs(#20049,13,#20047,0,"foo.baz()") +#20050=@"loc,{#10000},6,13,6,21" +locations_default(#20050,#10000,6,13,6,21) +hasLocation(#20049,#20050) +enclosing_stmt(#20049,#20047) +expr_containers(#20049,#20002) +#20051=* +exprs(#20051,14,#20049,-1,"foo.baz") +#20052=@"loc,{#10000},6,13,6,19" +locations_default(#20052,#10000,6,13,6,19) +hasLocation(#20051,#20052) +enclosing_stmt(#20051,#20047) +expr_containers(#20051,#20002) #20053=* -exprs(#20053,0,#20050,1,"baz") -hasLocation(#20053,#20025) -enclosing_stmt(#20053,#20046) -expr_containers(#20053,#20001) -literals("baz","baz",#20053) +exprs(#20053,79,#20051,0,"foo") +hasLocation(#20053,#20022) +enclosing_stmt(#20053,#20047) +expr_containers(#20053,#20002) +literals("foo","foo",#20053) +bind(#20053,#20037) #20054=* -entry_cfg_node(#20054,#20001) -hasLocation(#20054,#20003) +exprs(#20054,0,#20051,1,"baz") +hasLocation(#20054,#20026) +enclosing_stmt(#20054,#20047) +expr_containers(#20054,#20002) +literals("baz","baz",#20054) #20055=* -exit_cfg_node(#20055,#20001) -hasLocation(#20055,#20033) -successor(#20046,#20052) -successor(#20053,#20050) -successor(#20052,#20053) -successor(#20050,#20048) -successor(#20048,#20055) -successor(#20039,#20046) -successor(#20044,#20039) -successor(#20054,#20044) +entry_cfg_node(#20055,#20002) +hasLocation(#20055,#20004) #20056=* -toplevel_parent_xml_node(#20001,#20056) +exit_cfg_node(#20056,#20002) +hasLocation(#20056,#20034) +successor(#20047,#20053) +successor(#20054,#20051) +successor(#20053,#20054) +successor(#20051,#20049) +successor(#20049,#20056) +successor(#20040,#20047) +successor(#20045,#20040) +successor(#20055,#20045) +toplevel_parent_xml_node(#20002,#20001) #20057=* xmlElements(#20057,"html",#10000,0,#10000) #20058=@"loc,{#10000},1,1,11,7" @@ -210,12 +210,12 @@ 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) +xmlElements(#20001,"script",#20061,1,#10000) #20063=@"loc,{#10000},4,9,7,17" locations_default(#20063,#10000,4,9,7,17) -xmllocations(#20056,#20063) +xmllocations(#20001,#20063) #20064=* -xmlAttrs(#20064,#20056,"type","module",0,#10000) +xmlAttrs(#20064,#20001,"type","module",0,#10000) #20065=@"loc,{#10000},4,17,4,29" locations_default(#20065,#10000,4,17,4,29) xmllocations(#20064,#20065) diff --git a/javascript/extractor/tests/html/output/trap/tst.html.trap b/javascript/extractor/tests/html/output/trap/tst.html.trap index 73ea3e0382f..3f7e9362823 100644 --- a/javascript/extractor/tests/html/output/trap/tst.html.trap +++ b/javascript/extractor/tests/html/output/trap/tst.html.trap @@ -8,377 +8,377 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},5,17" -#20002=* -lines(#20002,#20001,""," +#20001=* +#20002=@"script;{#10000},5,17" +#20003=* +lines(#20003,#20002,""," ") -#20003=@"loc,{#10000},5,17,5,16" -locations_default(#20003,#10000,5,17,5,16) -hasLocation(#20002,#20003) -#20004=* -lines(#20004,#20001," alert(""Hello, world!"");"," +#20004=@"loc,{#10000},5,17,5,16" +locations_default(#20004,#10000,5,17,5,16) +hasLocation(#20003,#20004) +#20005=* +lines(#20005,#20002," alert(""Hello, world!"");"," ") -#20005=@"loc,{#10000},6,1,6,35" -locations_default(#20005,#10000,6,1,6,35) -hasLocation(#20004,#20005) +#20006=@"loc,{#10000},6,1,6,35" +locations_default(#20006,#10000,6,1,6,35) +hasLocation(#20005,#20006) indentation(#10000,6," ",12) -#20006=* -lines(#20006,#20001," ","") -#20007=@"loc,{#10000},7,1,7,8" -locations_default(#20007,#10000,7,1,7,8) -hasLocation(#20006,#20007) -numlines(#20001,3,1,0) -#20008=* -tokeninfo(#20008,6,#20001,0,"alert") -#20009=@"loc,{#10000},6,13,6,17" -locations_default(#20009,#10000,6,13,6,17) -hasLocation(#20008,#20009) -#20010=* -tokeninfo(#20010,8,#20001,1,"(") -#20011=@"loc,{#10000},6,18,6,18" -locations_default(#20011,#10000,6,18,6,18) -hasLocation(#20010,#20011) -#20012=* -tokeninfo(#20012,4,#20001,2,"""Hello, world!""") -#20013=@"loc,{#10000},6,19,6,33" -locations_default(#20013,#10000,6,19,6,33) -hasLocation(#20012,#20013) -#20014=* -tokeninfo(#20014,8,#20001,3,")") -#20015=@"loc,{#10000},6,34,6,34" -locations_default(#20015,#10000,6,34,6,34) -hasLocation(#20014,#20015) -#20016=* -tokeninfo(#20016,8,#20001,4,";") -#20017=@"loc,{#10000},6,35,6,35" -locations_default(#20017,#10000,6,35,6,35) -hasLocation(#20016,#20017) -#20018=* -tokeninfo(#20018,0,#20001,5,"") -#20019=@"loc,{#10000},7,9,7,8" -locations_default(#20019,#10000,7,9,7,8) -hasLocation(#20018,#20019) -toplevels(#20001,1) -#20020=@"loc,{#10000},5,17,7,8" -locations_default(#20020,#10000,5,17,7,8) -hasLocation(#20001,#20020) -#20021=* -stmts(#20021,2,#20001,0,"alert("" ... rld!"");") -#20022=@"loc,{#10000},6,13,6,35" -locations_default(#20022,#10000,6,13,6,35) -hasLocation(#20021,#20022) -stmt_containers(#20021,#20001) -#20023=* -exprs(#20023,13,#20021,0,"alert("" ... orld!"")") -#20024=@"loc,{#10000},6,13,6,34" -locations_default(#20024,#10000,6,13,6,34) -hasLocation(#20023,#20024) -enclosing_stmt(#20023,#20021) -expr_containers(#20023,#20001) -#20025=* -exprs(#20025,79,#20023,-1,"alert") -hasLocation(#20025,#20009) -enclosing_stmt(#20025,#20021) -expr_containers(#20025,#20001) -literals("alert","alert",#20025) -#20026=@"var;{alert};{#20000}" -variables(#20026,"alert",#20000) -bind(#20025,#20026) -#20027=* -exprs(#20027,4,#20023,0,"""Hello, world!""") -hasLocation(#20027,#20013) -enclosing_stmt(#20027,#20021) -expr_containers(#20027,#20001) -literals("Hello, world!","""Hello, world!""",#20027) +#20007=* +lines(#20007,#20002," ","") +#20008=@"loc,{#10000},7,1,7,8" +locations_default(#20008,#10000,7,1,7,8) +hasLocation(#20007,#20008) +numlines(#20002,3,1,0) +#20009=* +tokeninfo(#20009,6,#20002,0,"alert") +#20010=@"loc,{#10000},6,13,6,17" +locations_default(#20010,#10000,6,13,6,17) +hasLocation(#20009,#20010) +#20011=* +tokeninfo(#20011,8,#20002,1,"(") +#20012=@"loc,{#10000},6,18,6,18" +locations_default(#20012,#10000,6,18,6,18) +hasLocation(#20011,#20012) +#20013=* +tokeninfo(#20013,4,#20002,2,"""Hello, world!""") +#20014=@"loc,{#10000},6,19,6,33" +locations_default(#20014,#10000,6,19,6,33) +hasLocation(#20013,#20014) +#20015=* +tokeninfo(#20015,8,#20002,3,")") +#20016=@"loc,{#10000},6,34,6,34" +locations_default(#20016,#10000,6,34,6,34) +hasLocation(#20015,#20016) +#20017=* +tokeninfo(#20017,8,#20002,4,";") +#20018=@"loc,{#10000},6,35,6,35" +locations_default(#20018,#10000,6,35,6,35) +hasLocation(#20017,#20018) +#20019=* +tokeninfo(#20019,0,#20002,5,"") +#20020=@"loc,{#10000},7,9,7,8" +locations_default(#20020,#10000,7,9,7,8) +hasLocation(#20019,#20020) +toplevels(#20002,1) +#20021=@"loc,{#10000},5,17,7,8" +locations_default(#20021,#10000,5,17,7,8) +hasLocation(#20002,#20021) +#20022=* +stmts(#20022,2,#20002,0,"alert("" ... rld!"");") +#20023=@"loc,{#10000},6,13,6,35" +locations_default(#20023,#10000,6,13,6,35) +hasLocation(#20022,#20023) +stmt_containers(#20022,#20002) +#20024=* +exprs(#20024,13,#20022,0,"alert("" ... orld!"")") +#20025=@"loc,{#10000},6,13,6,34" +locations_default(#20025,#10000,6,13,6,34) +hasLocation(#20024,#20025) +enclosing_stmt(#20024,#20022) +expr_containers(#20024,#20002) +#20026=* +exprs(#20026,79,#20024,-1,"alert") +hasLocation(#20026,#20010) +enclosing_stmt(#20026,#20022) +expr_containers(#20026,#20002) +literals("alert","alert",#20026) +#20027=@"var;{alert};{#20000}" +variables(#20027,"alert",#20000) +bind(#20026,#20027) #20028=* -regexpterm(#20028,14,#20027,0,"Hello, world!") -#20029=@"loc,{#10000},6,20,6,32" -locations_default(#20029,#10000,6,20,6,32) -hasLocation(#20028,#20029) -regexp_const_value(#20028,"Hello, world!") -#20030=* -entry_cfg_node(#20030,#20001) -hasLocation(#20030,#20003) +exprs(#20028,4,#20024,0,"""Hello, world!""") +hasLocation(#20028,#20014) +enclosing_stmt(#20028,#20022) +expr_containers(#20028,#20002) +literals("Hello, world!","""Hello, world!""",#20028) +#20029=* +regexpterm(#20029,14,#20028,0,"Hello, world!") +#20030=@"loc,{#10000},6,20,6,32" +locations_default(#20030,#10000,6,20,6,32) +hasLocation(#20029,#20030) +regexp_const_value(#20029,"Hello, world!") #20031=* -exit_cfg_node(#20031,#20001) -hasLocation(#20031,#20019) -successor(#20021,#20025) -successor(#20027,#20023) -successor(#20025,#20027) -successor(#20023,#20031) -successor(#20030,#20021) +entry_cfg_node(#20031,#20002) +hasLocation(#20031,#20004) #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,8,#20033,0,";") -hasLocation(#20036,#20035) +exit_cfg_node(#20032,#20002) +hasLocation(#20032,#20020) +successor(#20022,#20026) +successor(#20028,#20024) +successor(#20026,#20028) +successor(#20024,#20032) +successor(#20031,#20022) +toplevel_parent_xml_node(#20002,#20001) +#20033=* +#20034=@"script;{#10000},8,17" +#20035=* +lines(#20035,#20034,";","") +#20036=@"loc,{#10000},8,17,8,17" +locations_default(#20036,#10000,8,17,8,17) +hasLocation(#20035,#20036) +numlines(#20034,1,1,0) #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=* -stmts(#20039,0,#20033,0,";") -hasLocation(#20039,#20035) -stmt_containers(#20039,#20033) +tokeninfo(#20037,8,#20034,0,";") +hasLocation(#20037,#20036) +#20038=* +tokeninfo(#20038,0,#20034,1,"") +#20039=@"loc,{#10000},8,18,8,17" +locations_default(#20039,#10000,8,18,8,17) +hasLocation(#20038,#20039) +toplevels(#20034,1) +hasLocation(#20034,#20036) #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) +stmts(#20040,0,#20034,0,";") +hasLocation(#20040,#20036) +stmt_containers(#20040,#20034) +#20041=* +entry_cfg_node(#20041,#20034) +#20042=@"loc,{#10000},8,17,8,16" +locations_default(#20042,#10000,8,17,8,16) +hasLocation(#20041,#20042) #20043=* -toplevel_parent_xml_node(#20033,#20043) -#20044=@"script;{#10000},11,29" -#20045=* -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,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,8,#20044,1,"(") -#20050=@"loc,{#10000},11,33,11,33" -locations_default(#20050,#10000,11,33,11,33) -hasLocation(#20049,#20050) -#20051=* -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,8,#20044,3,"(") -#20054=@"loc,{#10000},11,39,11,39" -locations_default(#20054,#10000,11,39,11,39) -hasLocation(#20053,#20054) -#20055=* -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,#20044,5,")") -#20058=@"loc,{#10000},11,47,11,47" -locations_default(#20058,#10000,11,47,11,47) -hasLocation(#20057,#20058) -#20059=* -tokeninfo(#20059,8,#20044,6,")") -#20060=@"loc,{#10000},11,48,11,48" -locations_default(#20060,#10000,11,48,11,48) -hasLocation(#20059,#20060) -#20061=* -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=* -stmts(#20063,2,#20044,0,"void(alert('Nope!'))") -hasLocation(#20063,#20046) -stmt_containers(#20063,#20044) +exit_cfg_node(#20043,#20034) +hasLocation(#20043,#20039) +successor(#20040,#20043) +successor(#20041,#20040) +toplevel_parent_xml_node(#20034,#20033) +#20044=* +#20045=@"script;{#10000},11,29" +#20046=* +lines(#20046,#20045,"void(alert('Nope!'))","") +#20047=@"loc,{#10000},11,29,11,48" +locations_default(#20047,#10000,11,29,11,48) +hasLocation(#20046,#20047) +numlines(#20045,1,1,0) +#20048=* +tokeninfo(#20048,7,#20045,0,"void") +#20049=@"loc,{#10000},11,29,11,32" +locations_default(#20049,#10000,11,29,11,32) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,8,#20045,1,"(") +#20051=@"loc,{#10000},11,33,11,33" +locations_default(#20051,#10000,11,33,11,33) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,6,#20045,2,"alert") +#20053=@"loc,{#10000},11,34,11,38" +locations_default(#20053,#10000,11,34,11,38) +hasLocation(#20052,#20053) +#20054=* +tokeninfo(#20054,8,#20045,3,"(") +#20055=@"loc,{#10000},11,39,11,39" +locations_default(#20055,#10000,11,39,11,39) +hasLocation(#20054,#20055) +#20056=* +tokeninfo(#20056,4,#20045,4,"'Nope!'") +#20057=@"loc,{#10000},11,40,11,46" +locations_default(#20057,#10000,11,40,11,46) +hasLocation(#20056,#20057) +#20058=* +tokeninfo(#20058,8,#20045,5,")") +#20059=@"loc,{#10000},11,47,11,47" +locations_default(#20059,#10000,11,47,11,47) +hasLocation(#20058,#20059) +#20060=* +tokeninfo(#20060,8,#20045,6,")") +#20061=@"loc,{#10000},11,48,11,48" +locations_default(#20061,#10000,11,48,11,48) +hasLocation(#20060,#20061) +#20062=* +tokeninfo(#20062,0,#20045,7,"") +#20063=@"loc,{#10000},11,49,11,48" +locations_default(#20063,#10000,11,49,11,48) +hasLocation(#20062,#20063) +toplevels(#20045,3) +hasLocation(#20045,#20047) #20064=* -exprs(#20064,21,#20063,0,"void(alert('Nope!'))") -hasLocation(#20064,#20046) -enclosing_stmt(#20064,#20063) -expr_containers(#20064,#20044) +stmts(#20064,2,#20045,0,"void(alert('Nope!'))") +hasLocation(#20064,#20047) +stmt_containers(#20064,#20045) #20065=* -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,#20063) -expr_containers(#20065,#20044) -#20067=* -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=* -exprs(#20069,79,#20067,-1,"alert") -hasLocation(#20069,#20052) -enclosing_stmt(#20069,#20063) -expr_containers(#20069,#20044) -literals("alert","alert",#20069) -bind(#20069,#20026) +exprs(#20065,21,#20064,0,"void(alert('Nope!'))") +hasLocation(#20065,#20047) +enclosing_stmt(#20065,#20064) +expr_containers(#20065,#20045) +#20066=* +exprs(#20066,63,#20065,0,"(alert('Nope!'))") +#20067=@"loc,{#10000},11,33,11,48" +locations_default(#20067,#10000,11,33,11,48) +hasLocation(#20066,#20067) +enclosing_stmt(#20066,#20064) +expr_containers(#20066,#20045) +#20068=* +exprs(#20068,13,#20066,0,"alert('Nope!')") +#20069=@"loc,{#10000},11,34,11,47" +locations_default(#20069,#10000,11,34,11,47) +hasLocation(#20068,#20069) +enclosing_stmt(#20068,#20064) +expr_containers(#20068,#20045) #20070=* -exprs(#20070,4,#20067,0,"'Nope!'") -hasLocation(#20070,#20056) -enclosing_stmt(#20070,#20063) -expr_containers(#20070,#20044) -literals("Nope!","'Nope!'",#20070) +exprs(#20070,79,#20068,-1,"alert") +hasLocation(#20070,#20053) +enclosing_stmt(#20070,#20064) +expr_containers(#20070,#20045) +literals("alert","alert",#20070) +bind(#20070,#20027) #20071=* -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=* -entry_cfg_node(#20073,#20044) -#20074=@"loc,{#10000},11,29,11,28" -locations_default(#20074,#10000,11,29,11,28) -hasLocation(#20073,#20074) -#20075=* -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) +exprs(#20071,4,#20068,0,"'Nope!'") +hasLocation(#20071,#20057) +enclosing_stmt(#20071,#20064) +expr_containers(#20071,#20045) +literals("Nope!","'Nope!'",#20071) +#20072=* +regexpterm(#20072,14,#20071,0,"Nope!") +#20073=@"loc,{#10000},11,41,11,45" +locations_default(#20073,#10000,11,41,11,45) +hasLocation(#20072,#20073) +regexp_const_value(#20072,"Nope!") +#20074=* +entry_cfg_node(#20074,#20045) +#20075=@"loc,{#10000},11,29,11,28" +locations_default(#20075,#10000,11,29,11,28) +hasLocation(#20074,#20075) #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=* -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=* -stmts(#20090,2,#20077,0,"alert(' ... lick!')") -hasLocation(#20090,#20079) -stmt_containers(#20090,#20077) +exit_cfg_node(#20076,#20045) +hasLocation(#20076,#20063) +successor(#20064,#20066) +successor(#20066,#20070) +successor(#20071,#20068) +successor(#20070,#20071) +successor(#20068,#20065) +successor(#20065,#20076) +successor(#20074,#20064) +toplevel_parent_xml_node(#20045,#20044) +#20077=* +#20078=@"script;{#10000},12,23" +#20079=* +lines(#20079,#20078,"alert('I said don\'t click!')","") +#20080=@"loc,{#10000},12,23,12,51" +locations_default(#20080,#10000,12,23,12,51) +hasLocation(#20079,#20080) +numlines(#20078,1,1,0) +#20081=* +tokeninfo(#20081,6,#20078,0,"alert") +#20082=@"loc,{#10000},12,23,12,27" +locations_default(#20082,#10000,12,23,12,27) +hasLocation(#20081,#20082) +#20083=* +tokeninfo(#20083,8,#20078,1,"(") +#20084=@"loc,{#10000},12,28,12,28" +locations_default(#20084,#10000,12,28,12,28) +hasLocation(#20083,#20084) +#20085=* +tokeninfo(#20085,4,#20078,2,"'I said don\'t click!'") +#20086=@"loc,{#10000},12,29,12,50" +locations_default(#20086,#10000,12,29,12,50) +hasLocation(#20085,#20086) +#20087=* +tokeninfo(#20087,8,#20078,3,")") +#20088=@"loc,{#10000},12,51,12,51" +locations_default(#20088,#10000,12,51,12,51) +hasLocation(#20087,#20088) +#20089=* +tokeninfo(#20089,0,#20078,4,"") +#20090=@"loc,{#10000},12,52,12,51" +locations_default(#20090,#10000,12,52,12,51) +hasLocation(#20089,#20090) +toplevels(#20078,2) +hasLocation(#20078,#20080) #20091=* -exprs(#20091,13,#20090,0,"alert(' ... lick!')") -hasLocation(#20091,#20079) -enclosing_stmt(#20091,#20090) -expr_containers(#20091,#20077) +stmts(#20091,2,#20078,0,"alert(' ... lick!')") +hasLocation(#20091,#20080) +stmt_containers(#20091,#20078) #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) +exprs(#20092,13,#20091,0,"alert(' ... lick!')") +hasLocation(#20092,#20080) +enclosing_stmt(#20092,#20091) +expr_containers(#20092,#20078) #20093=* -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) +exprs(#20093,79,#20092,-1,"alert") +hasLocation(#20093,#20082) +enclosing_stmt(#20093,#20091) +expr_containers(#20093,#20078) +literals("alert","alert",#20093) +bind(#20093,#20027) #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) +exprs(#20094,4,#20092,0,"'I said ... click!'") +hasLocation(#20094,#20086) +enclosing_stmt(#20094,#20091) +expr_containers(#20094,#20078) +literals("I said don't click!","'I said don\'t click!'",#20094) +#20095=* +regexpterm(#20095,14,#20094,0,"I said don't click!") +#20096=@"loc,{#10000},12,30,12,49" +locations_default(#20096,#10000,12,30,12,49) +hasLocation(#20095,#20096) +regexp_const_value(#20095,"I said don't click!") +#20097=* +entry_cfg_node(#20097,#20078) +#20098=@"loc,{#10000},12,23,12,22" +locations_default(#20098,#10000,12,23,12,22) +hasLocation(#20097,#20098) #20099=* -toplevel_parent_xml_node(#20077,#20099) -#20100=@"script;{#10000},13,21" -#20101=* -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,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,2,#20100,1,"false") -#20106=@"loc,{#10000},13,28,13,32" -locations_default(#20106,#10000,13,28,13,32) -hasLocation(#20105,#20106) -#20107=* -tokeninfo(#20107,8,#20100,2,";") -#20108=@"loc,{#10000},13,33,13,33" -locations_default(#20108,#10000,13,33,13,33) -hasLocation(#20107,#20108) -#20109=* -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=* -stmts(#20111,9,#20100,0,"return false;") -hasLocation(#20111,#20102) -stmt_containers(#20111,#20100) +exit_cfg_node(#20099,#20078) +hasLocation(#20099,#20090) +successor(#20091,#20093) +successor(#20094,#20092) +successor(#20093,#20094) +successor(#20092,#20099) +successor(#20097,#20091) +toplevel_parent_xml_node(#20078,#20077) +#20100=* +#20101=@"script;{#10000},13,21" +#20102=* +lines(#20102,#20101,"return false;","") +#20103=@"loc,{#10000},13,21,13,33" +locations_default(#20103,#10000,13,21,13,33) +hasLocation(#20102,#20103) +numlines(#20101,1,1,0) +#20104=* +tokeninfo(#20104,7,#20101,0,"return") +#20105=@"loc,{#10000},13,21,13,26" +locations_default(#20105,#10000,13,21,13,26) +hasLocation(#20104,#20105) +#20106=* +tokeninfo(#20106,2,#20101,1,"false") +#20107=@"loc,{#10000},13,28,13,32" +locations_default(#20107,#10000,13,28,13,32) +hasLocation(#20106,#20107) +#20108=* +tokeninfo(#20108,8,#20101,2,";") +#20109=@"loc,{#10000},13,33,13,33" +locations_default(#20109,#10000,13,33,13,33) +hasLocation(#20108,#20109) +#20110=* +tokeninfo(#20110,0,#20101,3,"") +#20111=@"loc,{#10000},13,34,13,33" +locations_default(#20111,#10000,13,34,13,33) +hasLocation(#20110,#20111) +toplevels(#20101,2) +hasLocation(#20101,#20103) #20112=* -exprs(#20112,2,#20111,0,"false") -hasLocation(#20112,#20106) -enclosing_stmt(#20112,#20111) -expr_containers(#20112,#20100) -literals("false","false",#20112) +stmts(#20112,9,#20101,0,"return false;") +hasLocation(#20112,#20103) +stmt_containers(#20112,#20101) #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) +exprs(#20113,2,#20112,0,"false") +hasLocation(#20113,#20107) +enclosing_stmt(#20113,#20112) +expr_containers(#20113,#20101) +literals("false","false",#20113) +#20114=* +entry_cfg_node(#20114,#20101) +#20115=@"loc,{#10000},13,21,13,20" +locations_default(#20115,#10000,13,21,13,20) +hasLocation(#20114,#20115) #20116=* -toplevel_parent_xml_node(#20100,#20116) +exit_cfg_node(#20116,#20101) +hasLocation(#20116,#20111) +successor(#20113,#20112) +successor(#20112,#20116) +successor(#20114,#20113) +toplevel_parent_xml_node(#20101,#20100) #20117=* xmlElements(#20117,"html",#10000,0,#10000) #20118=@"loc,{#10000},1,1,18,7" @@ -405,74 +405,180 @@ xmlAttrs(#20125,#20123,"TYPE","text/x-handlebars-template",0,#10000) 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) +template_placeholder_tag_info(#20127,#20123,"{{name}}") +#20128=@"loc,{#10000},16,54,16,61" +locations_default(#20128,#10000,16,54,16,61) +hasLocation(#20127,#20128) +scopes(#20000,0) +#20129=@"script;{#10000},16,56" +#20130=* +lines(#20130,#20129,"name","") +#20131=@"loc,{#10000},16,56,16,59" +locations_default(#20131,#10000,16,56,16,59) +hasLocation(#20130,#20131) +numlines(#20129,1,1,0) +#20132=* +tokeninfo(#20132,6,#20129,0,"name") +hasLocation(#20132,#20131) #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) +tokeninfo(#20133,0,#20129,1,"") +#20134=@"loc,{#10000},16,60,16,59" +locations_default(#20134,#10000,16,60,16,59) +hasLocation(#20133,#20134) +toplevels(#20129,4) +hasLocation(#20129,#20131) +#20135=@"module;{#10000},16,56" +scopes(#20135,3) +scopenodes(#20129,#20135) +scopenesting(#20135,#20000) +is_module(#20129) #20136=* -xmlElements(#20136,"div",#20131,1,#10000) -#20137=@"loc,{#10000},12,9,12,75" -locations_default(#20137,#10000,12,9,12,75) -xmllocations(#20136,#20137) -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) +stmts(#20136,2,#20129,0,"name") +hasLocation(#20136,#20131) +stmt_containers(#20136,#20129) +#20137=* +exprs(#20137,79,#20136,0,"name") +hasLocation(#20137,#20131) +enclosing_stmt(#20137,#20136) +expr_containers(#20137,#20129) +literals("name","name",#20137) +#20138=@"var;{name};{#20135}" +variables(#20138,"name",#20135) +bind(#20137,#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) +entry_cfg_node(#20139,#20129) +#20140=@"loc,{#10000},16,56,16,55" +locations_default(#20140,#10000,16,56,16,55) +hasLocation(#20139,#20140) +#20141=* +exit_cfg_node(#20141,#20129) +hasLocation(#20141,#20134) +successor(#20136,#20137) +successor(#20137,#20141) +successor(#20139,#20136) +toplevel_parent_xml_node(#20129,#20127) #20142=* -xmlElements(#20142,"head",#20117,0,#10000) -#20143=@"loc,{#10000},2,5,9,11" -locations_default(#20143,#10000,2,5,9,11) +xmlElements(#20142,"script",#20117,2,#10000) +#20143=@"loc,{#10000},15,5,15,71" +locations_default(#20143,#10000,15,5,15,71) xmllocations(#20142,#20143) -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(#20032,#20145) +#20144=* +xmlAttrs(#20144,#20142,"type","text/x-handlebars-template",0,#10000) +#20145=@"loc,{#10000},15,13,15,45" +locations_default(#20145,#10000,15,13,15,45) +xmllocations(#20144,#20145) #20146=* -xmlElements(#20146,"script",#20142,1,#10000) -#20147=@"loc,{#10000},4,9,4,43" -locations_default(#20147,#10000,4,9,4,43) -xmllocations(#20146,#20147) -#20148=* -xmlAttrs(#20148,#20146,"src","external.js",0,#10000) -#20149=@"loc,{#10000},4,17,4,33" -locations_default(#20149,#10000,4,17,4,33) -xmllocations(#20148,#20149) -#20150=* -xmlElements(#20150,"title",#20142,0,#10000) -#20151=@"loc,{#10000},3,9,3,32" -locations_default(#20151,#10000,3,9,3,32) -xmllocations(#20150,#20151) -numlines(#10000,18,5,0) +template_placeholder_tag_info(#20146,#20142,"{{name}}") +#20147=@"loc,{#10000},15,54,15,61" +locations_default(#20147,#10000,15,54,15,61) +hasLocation(#20146,#20147) +scopes(#20000,0) +#20148=@"script;{#10000},15,56" +#20149=* +lines(#20149,#20148,"name","") +#20150=@"loc,{#10000},15,56,15,59" +locations_default(#20150,#10000,15,56,15,59) +hasLocation(#20149,#20150) +numlines(#20148,1,1,0) +#20151=* +tokeninfo(#20151,6,#20148,0,"name") +hasLocation(#20151,#20150) +#20152=* +tokeninfo(#20152,0,#20148,1,"") +#20153=@"loc,{#10000},15,60,15,59" +locations_default(#20153,#10000,15,60,15,59) +hasLocation(#20152,#20153) +toplevels(#20148,4) +hasLocation(#20148,#20150) +#20154=@"module;{#10000},15,56" +scopes(#20154,3) +scopenodes(#20148,#20154) +scopenesting(#20154,#20000) +is_module(#20148) +#20155=* +stmts(#20155,2,#20148,0,"name") +hasLocation(#20155,#20150) +stmt_containers(#20155,#20148) +#20156=* +exprs(#20156,79,#20155,0,"name") +hasLocation(#20156,#20150) +enclosing_stmt(#20156,#20155) +expr_containers(#20156,#20148) +literals("name","name",#20156) +#20157=@"var;{name};{#20154}" +variables(#20157,"name",#20154) +bind(#20156,#20157) +#20158=* +entry_cfg_node(#20158,#20148) +#20159=@"loc,{#10000},15,56,15,55" +locations_default(#20159,#10000,15,56,15,55) +hasLocation(#20158,#20159) +#20160=* +exit_cfg_node(#20160,#20148) +hasLocation(#20160,#20153) +successor(#20155,#20156) +successor(#20156,#20160) +successor(#20158,#20155) +toplevel_parent_xml_node(#20148,#20146) +#20161=* +xmlElements(#20161,"body",#20117,1,#10000) +#20162=@"loc,{#10000},10,5,14,11" +locations_default(#20162,#10000,10,5,14,11) +xmllocations(#20161,#20162) +#20163=* +xmlElements(#20163,"a",#20161,2,#10000) +#20164=@"loc,{#10000},13,9,13,59" +locations_default(#20164,#10000,13,9,13,59) +xmllocations(#20163,#20164) +xmlAttrs(#20100,#20163,"onclick","return false;",0,#10000) +#20165=@"loc,{#10000},13,12,13,34" +locations_default(#20165,#10000,13,12,13,34) +xmllocations(#20100,#20165) +#20166=* +xmlElements(#20166,"div",#20161,1,#10000) +#20167=@"loc,{#10000},12,9,12,75" +locations_default(#20167,#10000,12,9,12,75) +xmllocations(#20166,#20167) +xmlAttrs(#20077,#20166,"onclick","alert('I said don\'t click!')",0,#10000) +#20168=@"loc,{#10000},12,14,12,52" +locations_default(#20168,#10000,12,14,12,52) +xmllocations(#20077,#20168) +#20169=* +xmlElements(#20169,"a",#20161,0,#10000) +#20170=@"loc,{#10000},11,9,11,64" +locations_default(#20170,#10000,11,9,11,64) +xmllocations(#20169,#20170) +xmlAttrs(#20044,#20169,"href","javascript:void(alert('Nope!'))",0,#10000) +#20171=@"loc,{#10000},11,12,11,49" +locations_default(#20171,#10000,11,12,11,49) +xmllocations(#20044,#20171) +#20172=* +xmlElements(#20172,"head",#20117,0,#10000) +#20173=@"loc,{#10000},2,5,9,11" +locations_default(#20173,#10000,2,5,9,11) +xmllocations(#20172,#20173) +xmlElements(#20033,"script",#20172,3,#10000) +#20174=@"loc,{#10000},8,9,8,26" +locations_default(#20174,#10000,8,9,8,26) +xmllocations(#20033,#20174) +xmlElements(#20001,"script",#20172,2,#10000) +#20175=@"loc,{#10000},5,9,7,17" +locations_default(#20175,#10000,5,9,7,17) +xmllocations(#20001,#20175) +#20176=* +xmlElements(#20176,"script",#20172,1,#10000) +#20177=@"loc,{#10000},4,9,4,43" +locations_default(#20177,#10000,4,9,4,43) +xmllocations(#20176,#20177) +#20178=* +xmlAttrs(#20178,#20176,"src","external.js",0,#10000) +#20179=@"loc,{#10000},4,17,4,33" +locations_default(#20179,#10000,4,17,4,33) +xmllocations(#20178,#20179) +#20180=* +xmlElements(#20180,"title",#20172,0,#10000) +#20181=@"loc,{#10000},3,9,3,32" +locations_default(#20181,#10000,3,9,3,32) +xmllocations(#20180,#20181) +numlines(#10000,18,7,0) filetype(#10000,"html") diff --git a/javascript/extractor/tests/html/output/trap/tst.xhtml.trap b/javascript/extractor/tests/html/output/trap/tst.xhtml.trap index 9b874e74b95..286c6f0175c 100644 --- a/javascript/extractor/tests/html/output/trap/tst.xhtml.trap +++ b/javascript/extractor/tests/html/output/trap/tst.xhtml.trap @@ -8,74 +8,74 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},7,43" -#20002=* -lines(#20002,#20001,""," +#20001=* +#20002=@"script;{#10000},7,43" +#20003=* +lines(#20003,#20002,""," ") -#20003=@"loc,{#10000},7,43,7,42" -locations_default(#20003,#10000,7,43,7,42) -hasLocation(#20002,#20003) -#20004=* -lines(#20004,#20001," "," +#20004=@"loc,{#10000},7,43,7,42" +locations_default(#20004,#10000,7,43,7,42) +hasLocation(#20003,#20004) +#20005=* +lines(#20005,#20002," "," ") -#20005=@"loc,{#10000},8,1,8,14" -locations_default(#20005,#10000,8,1,8,14) -hasLocation(#20004,#20005) -#20006=* -lines(#20006,#20001," 42;"," +#20006=@"loc,{#10000},8,1,8,14" +locations_default(#20006,#10000,8,1,8,14) +hasLocation(#20005,#20006) +#20007=* +lines(#20007,#20002," 42;"," ") -#20007=@"loc,{#10000},9,1,9,7" -locations_default(#20007,#10000,9,1,9,7) -hasLocation(#20006,#20007) +#20008=@"loc,{#10000},9,1,9,7" +locations_default(#20008,#10000,9,1,9,7) +hasLocation(#20007,#20008) indentation(#10000,9," ",4) -#20008=* -lines(#20008,#20001," ","") -#20009=@"loc,{#10000},10,1,10,7" -locations_default(#20009,#10000,10,1,10,7) -hasLocation(#20008,#20009) -numlines(#20001,4,1,0) -#20010=* -tokeninfo(#20010,3,#20001,0,"42") -#20011=@"loc,{#10000},9,5,9,6" -locations_default(#20011,#10000,9,5,9,6) -hasLocation(#20010,#20011) -#20012=* -tokeninfo(#20012,8,#20001,1,";") -#20013=@"loc,{#10000},9,7,9,7" -locations_default(#20013,#10000,9,7,9,7) -hasLocation(#20012,#20013) -#20014=* -tokeninfo(#20014,0,#20001,2,"") -#20015=@"loc,{#10000},10,8,10,7" -locations_default(#20015,#10000,10,8,10,7) -hasLocation(#20014,#20015) -toplevels(#20001,1) -#20016=@"loc,{#10000},7,43,10,7" -locations_default(#20016,#10000,7,43,10,7) -hasLocation(#20001,#20016) -#20017=* -stmts(#20017,2,#20001,0,"42;") -#20018=@"loc,{#10000},9,5,9,7" -locations_default(#20018,#10000,9,5,9,7) -hasLocation(#20017,#20018) -stmt_containers(#20017,#20001) -#20019=* -exprs(#20019,3,#20017,0,"42") -hasLocation(#20019,#20011) -enclosing_stmt(#20019,#20017) -expr_containers(#20019,#20001) -literals("42","42",#20019) +#20009=* +lines(#20009,#20002," ","") +#20010=@"loc,{#10000},10,1,10,7" +locations_default(#20010,#10000,10,1,10,7) +hasLocation(#20009,#20010) +numlines(#20002,4,1,0) +#20011=* +tokeninfo(#20011,3,#20002,0,"42") +#20012=@"loc,{#10000},9,5,9,6" +locations_default(#20012,#10000,9,5,9,6) +hasLocation(#20011,#20012) +#20013=* +tokeninfo(#20013,8,#20002,1,";") +#20014=@"loc,{#10000},9,7,9,7" +locations_default(#20014,#10000,9,7,9,7) +hasLocation(#20013,#20014) +#20015=* +tokeninfo(#20015,0,#20002,2,"") +#20016=@"loc,{#10000},10,8,10,7" +locations_default(#20016,#10000,10,8,10,7) +hasLocation(#20015,#20016) +toplevels(#20002,1) +#20017=@"loc,{#10000},7,43,10,7" +locations_default(#20017,#10000,7,43,10,7) +hasLocation(#20002,#20017) +#20018=* +stmts(#20018,2,#20002,0,"42;") +#20019=@"loc,{#10000},9,5,9,7" +locations_default(#20019,#10000,9,5,9,7) +hasLocation(#20018,#20019) +stmt_containers(#20018,#20002) #20020=* -entry_cfg_node(#20020,#20001) -hasLocation(#20020,#20003) +exprs(#20020,3,#20018,0,"42") +hasLocation(#20020,#20012) +enclosing_stmt(#20020,#20018) +expr_containers(#20020,#20002) +literals("42","42",#20020) #20021=* -exit_cfg_node(#20021,#20001) -hasLocation(#20021,#20015) -successor(#20017,#20019) -successor(#20019,#20021) -successor(#20020,#20017) +entry_cfg_node(#20021,#20002) +hasLocation(#20021,#20004) #20022=* -toplevel_parent_xml_node(#20001,#20022) +exit_cfg_node(#20022,#20002) +hasLocation(#20022,#20016) +successor(#20018,#20020) +successor(#20020,#20022) +successor(#20021,#20018) +toplevel_parent_xml_node(#20002,#20001) #20023=* xmlElements(#20023,"html",#10000,0,#10000) #20024=@"loc,{#10000},2,1,12,7" @@ -96,12 +96,12 @@ 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) +xmlElements(#20001,"script",#20029,0,#10000) #20031=@"loc,{#10000},7,5,10,16" locations_default(#20031,#10000,7,5,10,16) -xmllocations(#20022,#20031) +xmllocations(#20001,#20031) #20032=* -xmlAttrs(#20032,#20022,"type","application/javascript",0,#10000) +xmlAttrs(#20032,#20001,"type","application/javascript",0,#10000) #20033=@"loc,{#10000},7,13,7,41" locations_default(#20033,#10000,7,13,7,41) xmllocations(#20032,#20033) diff --git a/javascript/extractor/tests/html/output/trap/tst2.html.trap b/javascript/extractor/tests/html/output/trap/tst2.html.trap index 050936eb14e..d47d40c899d 100644 --- a/javascript/extractor/tests/html/output/trap/tst2.html.trap +++ b/javascript/extractor/tests/html/output/trap/tst2.html.trap @@ -8,365 +8,365 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},2,31" -#20002=* -lines(#20002,#20001,"var hello;","") -#20003=@"loc,{#10000},2,31,2,40" -locations_default(#20003,#10000,2,31,2,40) -hasLocation(#20002,#20003) -numlines(#20001,1,1,0) -#20004=* -tokeninfo(#20004,7,#20001,0,"var") -#20005=@"loc,{#10000},2,31,2,33" -locations_default(#20005,#10000,2,31,2,33) -hasLocation(#20004,#20005) -#20006=* -tokeninfo(#20006,6,#20001,1,"hello") -#20007=@"loc,{#10000},2,35,2,39" -locations_default(#20007,#10000,2,35,2,39) -hasLocation(#20006,#20007) -#20008=* -tokeninfo(#20008,8,#20001,2,";") -#20009=@"loc,{#10000},2,40,2,40" -locations_default(#20009,#10000,2,40,2,40) -hasLocation(#20008,#20009) -#20010=* -tokeninfo(#20010,0,#20001,3,"") -#20011=@"loc,{#10000},2,41,2,40" -locations_default(#20011,#10000,2,41,2,40) -hasLocation(#20010,#20011) -toplevels(#20001,1) -hasLocation(#20001,#20003) -#20012=@"var;{hello};{#20000}" -variables(#20012,"hello",#20000) -#20013=* -stmts(#20013,18,#20001,0,"var hello;") -hasLocation(#20013,#20003) -stmt_containers(#20013,#20001) +#20001=* +#20002=@"script;{#10000},2,31" +#20003=* +lines(#20003,#20002,"var hello;","") +#20004=@"loc,{#10000},2,31,2,40" +locations_default(#20004,#10000,2,31,2,40) +hasLocation(#20003,#20004) +numlines(#20002,1,1,0) +#20005=* +tokeninfo(#20005,7,#20002,0,"var") +#20006=@"loc,{#10000},2,31,2,33" +locations_default(#20006,#10000,2,31,2,33) +hasLocation(#20005,#20006) +#20007=* +tokeninfo(#20007,6,#20002,1,"hello") +#20008=@"loc,{#10000},2,35,2,39" +locations_default(#20008,#10000,2,35,2,39) +hasLocation(#20007,#20008) +#20009=* +tokeninfo(#20009,8,#20002,2,";") +#20010=@"loc,{#10000},2,40,2,40" +locations_default(#20010,#10000,2,40,2,40) +hasLocation(#20009,#20010) +#20011=* +tokeninfo(#20011,0,#20002,3,"") +#20012=@"loc,{#10000},2,41,2,40" +locations_default(#20012,#10000,2,41,2,40) +hasLocation(#20011,#20012) +toplevels(#20002,1) +hasLocation(#20002,#20004) +#20013=@"var;{hello};{#20000}" +variables(#20013,"hello",#20000) #20014=* -exprs(#20014,64,#20013,0,"hello") -hasLocation(#20014,#20007) -enclosing_stmt(#20014,#20013) -expr_containers(#20014,#20001) +stmts(#20014,18,#20002,0,"var hello;") +hasLocation(#20014,#20004) +stmt_containers(#20014,#20002) #20015=* -exprs(#20015,78,#20014,0,"hello") -hasLocation(#20015,#20007) -enclosing_stmt(#20015,#20013) -expr_containers(#20015,#20001) -literals("hello","hello",#20015) -decl(#20015,#20012) +exprs(#20015,64,#20014,0,"hello") +hasLocation(#20015,#20008) +enclosing_stmt(#20015,#20014) +expr_containers(#20015,#20002) #20016=* -entry_cfg_node(#20016,#20001) -#20017=@"loc,{#10000},2,31,2,30" -locations_default(#20017,#10000,2,31,2,30) -hasLocation(#20016,#20017) -#20018=* -exit_cfg_node(#20018,#20001) -hasLocation(#20018,#20011) -successor(#20013,#20015) -successor(#20015,#20014) -successor(#20014,#20018) -successor(#20016,#20013) +exprs(#20016,78,#20015,0,"hello") +hasLocation(#20016,#20008) +enclosing_stmt(#20016,#20014) +expr_containers(#20016,#20002) +literals("hello","hello",#20016) +decl(#20016,#20013) +#20017=* +entry_cfg_node(#20017,#20002) +#20018=@"loc,{#10000},2,31,2,30" +locations_default(#20018,#10000,2,31,2,30) +hasLocation(#20017,#20018) #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=* -stmts(#20032,18,#20020,0,"var world;") -hasLocation(#20032,#20022) -stmt_containers(#20032,#20020) +exit_cfg_node(#20019,#20002) +hasLocation(#20019,#20012) +successor(#20014,#20016) +successor(#20016,#20015) +successor(#20015,#20019) +successor(#20017,#20014) +toplevel_parent_xml_node(#20002,#20001) +#20020=* +#20021=@"script;{#10000},3,29" +#20022=* +lines(#20022,#20021,"var world;","") +#20023=@"loc,{#10000},3,29,3,38" +locations_default(#20023,#10000,3,29,3,38) +hasLocation(#20022,#20023) +numlines(#20021,1,1,0) +#20024=* +tokeninfo(#20024,7,#20021,0,"var") +#20025=@"loc,{#10000},3,29,3,31" +locations_default(#20025,#10000,3,29,3,31) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,6,#20021,1,"world") +#20027=@"loc,{#10000},3,33,3,37" +locations_default(#20027,#10000,3,33,3,37) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,8,#20021,2,";") +#20029=@"loc,{#10000},3,38,3,38" +locations_default(#20029,#10000,3,38,3,38) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,0,#20021,3,"") +#20031=@"loc,{#10000},3,39,3,38" +locations_default(#20031,#10000,3,39,3,38) +hasLocation(#20030,#20031) +toplevels(#20021,1) +hasLocation(#20021,#20023) +#20032=@"var;{world};{#20000}" +variables(#20032,"world",#20000) #20033=* -exprs(#20033,64,#20032,0,"world") -hasLocation(#20033,#20026) -enclosing_stmt(#20033,#20032) -expr_containers(#20033,#20020) +stmts(#20033,18,#20021,0,"var world;") +hasLocation(#20033,#20023) +stmt_containers(#20033,#20021) #20034=* -exprs(#20034,78,#20033,0,"world") -hasLocation(#20034,#20026) -enclosing_stmt(#20034,#20032) -expr_containers(#20034,#20020) -literals("world","world",#20034) -decl(#20034,#20031) +exprs(#20034,64,#20033,0,"world") +hasLocation(#20034,#20027) +enclosing_stmt(#20034,#20033) +expr_containers(#20034,#20021) #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) +exprs(#20035,78,#20034,0,"world") +hasLocation(#20035,#20027) +enclosing_stmt(#20035,#20033) +expr_containers(#20035,#20021) +literals("world","world",#20035) +decl(#20035,#20032) +#20036=* +entry_cfg_node(#20036,#20021) +#20037=@"loc,{#10000},3,29,3,28" +locations_default(#20037,#10000,3,29,3,28) +hasLocation(#20036,#20037) #20038=* -toplevel_parent_xml_node(#20020,#20038) -#20039=@"script;{#10000},4,75" -#20040=* -lines(#20040,#20039,""," +exit_cfg_node(#20038,#20021) +hasLocation(#20038,#20031) +successor(#20033,#20035) +successor(#20035,#20034) +successor(#20034,#20038) +successor(#20036,#20033) +toplevel_parent_xml_node(#20021,#20020) +#20039=* +#20040=@"script;{#10000},4,75" +#20041=* +lines(#20041,#20040,""," ") -#20041=@"loc,{#10000},4,75,4,74" -locations_default(#20041,#10000,4,75,4,74) -hasLocation(#20040,#20041) -#20042=* -lines(#20042,#20039," var inAModule;"," +#20042=@"loc,{#10000},4,75,4,74" +locations_default(#20042,#10000,4,75,4,74) +hasLocation(#20041,#20042) +#20043=* +lines(#20043,#20040," var inAModule;"," ") -#20043=@"loc,{#10000},5,1,5,20" -locations_default(#20043,#10000,5,1,5,20) -hasLocation(#20042,#20043) +#20044=@"loc,{#10000},5,1,5,20" +locations_default(#20044,#10000,5,1,5,20) +hasLocation(#20043,#20044) indentation(#10000,5," ",6) -#20044=* -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,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,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,8,#20039,2,";") -#20051=@"loc,{#10000},5,20,5,20" -locations_default(#20051,#10000,5,20,5,20) -hasLocation(#20050,#20051) -#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=* -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=* -exprs(#20059,64,#20057,0,"inAModule") -hasLocation(#20059,#20049) -enclosing_stmt(#20059,#20057) -expr_containers(#20059,#20039) +#20045=* +lines(#20045,#20040," ","") +#20046=@"loc,{#10000},6,1,6,4" +locations_default(#20046,#10000,6,1,6,4) +hasLocation(#20045,#20046) +numlines(#20040,3,1,0) +#20047=* +tokeninfo(#20047,7,#20040,0,"var") +#20048=@"loc,{#10000},5,7,5,9" +locations_default(#20048,#10000,5,7,5,9) +hasLocation(#20047,#20048) +#20049=* +tokeninfo(#20049,6,#20040,1,"inAModule") +#20050=@"loc,{#10000},5,11,5,19" +locations_default(#20050,#10000,5,11,5,19) +hasLocation(#20049,#20050) +#20051=* +tokeninfo(#20051,8,#20040,2,";") +#20052=@"loc,{#10000},5,20,5,20" +locations_default(#20052,#10000,5,20,5,20) +hasLocation(#20051,#20052) +#20053=* +tokeninfo(#20053,0,#20040,3,"") +#20054=@"loc,{#10000},6,5,6,4" +locations_default(#20054,#10000,6,5,6,4) +hasLocation(#20053,#20054) +toplevels(#20040,1) +#20055=@"loc,{#10000},4,75,6,4" +locations_default(#20055,#10000,4,75,6,4) +hasLocation(#20040,#20055) +#20056=@"module;{#10000},4,75" +scopes(#20056,3) +scopenodes(#20040,#20056) +scopenesting(#20056,#20000) +is_module(#20040) +is_es2015_module(#20040) +#20057=@"var;{inAModule};{#20056}" +variables(#20057,"inAModule",#20056) +#20058=* +stmts(#20058,18,#20040,0,"var inAModule;") +#20059=@"loc,{#10000},5,7,5,20" +locations_default(#20059,#10000,5,7,5,20) +hasLocation(#20058,#20059) +stmt_containers(#20058,#20040) #20060=* -exprs(#20060,78,#20059,0,"inAModule") -hasLocation(#20060,#20049) -enclosing_stmt(#20060,#20057) -expr_containers(#20060,#20039) -literals("inAModule","inAModule",#20060) -decl(#20060,#20056) +exprs(#20060,64,#20058,0,"inAModule") +hasLocation(#20060,#20050) +enclosing_stmt(#20060,#20058) +expr_containers(#20060,#20040) #20061=* -entry_cfg_node(#20061,#20039) -hasLocation(#20061,#20041) +exprs(#20061,78,#20060,0,"inAModule") +hasLocation(#20061,#20050) +enclosing_stmt(#20061,#20058) +expr_containers(#20061,#20040) +literals("inAModule","inAModule",#20061) +decl(#20061,#20057) #20062=* -exit_cfg_node(#20062,#20039) -hasLocation(#20062,#20053) -successor(#20057,#20060) -successor(#20060,#20059) -successor(#20059,#20062) -successor(#20061,#20057) +entry_cfg_node(#20062,#20040) +hasLocation(#20062,#20042) #20063=* -toplevel_parent_xml_node(#20039,#20063) -#20064=@"script;{#10000},7,75" -#20065=* -lines(#20065,#20064,""," +exit_cfg_node(#20063,#20040) +hasLocation(#20063,#20054) +successor(#20058,#20061) +successor(#20061,#20060) +successor(#20060,#20063) +successor(#20062,#20058) +toplevel_parent_xml_node(#20040,#20039) +#20064=* +#20065=@"script;{#10000},7,75" +#20066=* +lines(#20066,#20065,""," ") -#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"""," +#20067=@"loc,{#10000},7,75,7,74" +locations_default(#20067,#10000,7,75,7,74) +hasLocation(#20066,#20067) +#20068=* +lines(#20068,#20065," import f from ""f"""," ") -#20068=@"loc,{#10000},8,1,8,23" -locations_default(#20068,#10000,8,1,8,23) -hasLocation(#20067,#20068) +#20069=@"loc,{#10000},8,1,8,23" +locations_default(#20069,#10000,8,1,8,23) +hasLocation(#20068,#20069) indentation(#10000,8," ",6) -#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=* -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) -stmt_containers(#20086,#20064) -#20088=* -exprs(#20088,4,#20086,-1,"""f""") -hasLocation(#20088,#20078) -enclosing_stmt(#20088,#20086) -expr_containers(#20088,#20064) -literals("f","""f""",#20088) +#20070=* +lines(#20070,#20065," ","") +#20071=@"loc,{#10000},9,1,9,4" +locations_default(#20071,#10000,9,1,9,4) +hasLocation(#20070,#20071) +numlines(#20065,3,1,0) +#20072=* +tokeninfo(#20072,7,#20065,0,"import") +#20073=@"loc,{#10000},8,7,8,12" +locations_default(#20073,#10000,8,7,8,12) +hasLocation(#20072,#20073) +#20074=* +tokeninfo(#20074,6,#20065,1,"f") +#20075=@"loc,{#10000},8,14,8,14" +locations_default(#20075,#10000,8,14,8,14) +hasLocation(#20074,#20075) +#20076=* +tokeninfo(#20076,6,#20065,2,"from") +#20077=@"loc,{#10000},8,16,8,19" +locations_default(#20077,#10000,8,16,8,19) +hasLocation(#20076,#20077) +#20078=* +tokeninfo(#20078,4,#20065,3,"""f""") +#20079=@"loc,{#10000},8,21,8,23" +locations_default(#20079,#10000,8,21,8,23) +hasLocation(#20078,#20079) +#20080=* +tokeninfo(#20080,0,#20065,4,"") +#20081=@"loc,{#10000},9,5,9,4" +locations_default(#20081,#10000,9,5,9,4) +hasLocation(#20080,#20081) +toplevels(#20065,1) +#20082=@"loc,{#10000},7,75,9,4" +locations_default(#20082,#10000,7,75,9,4) +hasLocation(#20065,#20082) +#20083=@"module;{#10000},7,75" +scopes(#20083,3) +scopenodes(#20065,#20083) +scopenesting(#20083,#20000) +is_module(#20065) +is_es2015_module(#20065) +#20084=@"var;{f};{#20083}" +variables(#20084,"f",#20083) +#20085=@"local_type_name;{f};{#20083}" +local_type_names(#20085,"f",#20083) +#20086=@"local_namespace_name;{f};{#20083}" +local_namespace_names(#20086,"f",#20083) +variables(#20084,"f",#20083) +local_type_names(#20085,"f",#20083) +local_namespace_names(#20086,"f",#20083) +#20087=* +stmts(#20087,27,#20065,0,"import f from ""f""") +#20088=@"loc,{#10000},8,7,8,23" +locations_default(#20088,#10000,8,7,8,23) +hasLocation(#20087,#20088) +stmt_containers(#20087,#20065) #20089=* -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=* -exprs(#20091,84,#20086,0,"f") -hasLocation(#20091,#20074) -enclosing_stmt(#20091,#20086) -expr_containers(#20091,#20064) +exprs(#20089,4,#20087,-1,"""f""") +hasLocation(#20089,#20079) +enclosing_stmt(#20089,#20087) +expr_containers(#20089,#20065) +literals("f","""f""",#20089) +#20090=* +regexpterm(#20090,14,#20089,0,"f") +#20091=@"loc,{#10000},8,22,8,22" +locations_default(#20091,#10000,8,22,8,22) +hasLocation(#20090,#20091) +regexp_const_value(#20090,"f") #20092=* -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) +exprs(#20092,84,#20087,0,"f") +hasLocation(#20092,#20075) +enclosing_stmt(#20092,#20087) +expr_containers(#20092,#20065) #20093=* -entry_cfg_node(#20093,#20064) -hasLocation(#20093,#20066) +exprs(#20093,78,#20092,1,"f") +hasLocation(#20093,#20075) +enclosing_stmt(#20093,#20087) +expr_containers(#20093,#20065) +literals("f","f",#20093) +decl(#20093,#20084) +typedecl(#20093,#20085) +namespacedecl(#20093,#20086) #20094=* -exit_cfg_node(#20094,#20064) -hasLocation(#20094,#20080) -successor(#20086,#20094) -successor(#20091,#20086) -successor(#20093,#20091) +entry_cfg_node(#20094,#20065) +hasLocation(#20094,#20067) #20095=* -toplevel_parent_xml_node(#20064,#20095) +exit_cfg_node(#20095,#20065) +hasLocation(#20095,#20081) +successor(#20087,#20095) +successor(#20092,#20087) +successor(#20094,#20092) +toplevel_parent_xml_node(#20065,#20064) #20096=* xmlElements(#20096,"html",#10000,0,#10000) #20097=@"loc,{#10000},1,1,10,7" locations_default(#20097,#10000,1,1,10,7) xmllocations(#20096,#20097) -xmlElements(#20095,"script",#20096,3,#10000) +xmlElements(#20064,"script",#20096,3,#10000) #20098=@"loc,{#10000},7,5,9,13" locations_default(#20098,#10000,7,5,9,13) -xmllocations(#20095,#20098) +xmllocations(#20064,#20098) #20099=* -xmlAttrs(#20099,#20095,"type","text/babel",0,#10000) +xmlAttrs(#20099,#20064,"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) +xmlAttrs(#20101,#20064,"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) +xmlElements(#20039,"script",#20096,2,#10000) #20103=@"loc,{#10000},4,5,6,13" locations_default(#20103,#10000,4,5,6,13) -xmllocations(#20063,#20103) +xmllocations(#20039,#20103) #20104=* -xmlAttrs(#20104,#20063,"type","text/babel",0,#10000) +xmlAttrs(#20104,#20039,"type","text/babel",0,#10000) #20105=@"loc,{#10000},4,13,4,29" locations_default(#20105,#10000,4,13,4,29) xmllocations(#20104,#20105) #20106=* -xmlAttrs(#20106,#20063,"data-plugins","transform-es2015-modules-umd",1,#10000) +xmlAttrs(#20106,#20039,"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) -xmlElements(#20038,"script",#20096,1,#10000) +xmlElements(#20020,"script",#20096,1,#10000) #20108=@"loc,{#10000},3,5,3,47" locations_default(#20108,#10000,3,5,3,47) -xmllocations(#20038,#20108) +xmllocations(#20020,#20108) #20109=* -xmlAttrs(#20109,#20038,"type","text/jsx",0,#10000) +xmlAttrs(#20109,#20020,"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) +xmlElements(#20001,"script",#20096,0,#10000) #20111=@"loc,{#10000},2,5,2,49" locations_default(#20111,#10000,2,5,2,49) -xmllocations(#20019,#20111) +xmllocations(#20001,#20111) #20112=* -xmlAttrs(#20112,#20019,"type","text/babel",0,#10000) +xmlAttrs(#20112,#20001,"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 5b6f54c005a..0d475cc7080 100644 --- a/javascript/extractor/tests/ng-templates/output/trap/component.js.trap +++ b/javascript/extractor/tests/ng-templates/output/trap/component.js.trap @@ -329,216 +329,216 @@ literals(" ",#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,4) -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) +#20100=* +#20101=@"script;{#10000},5,15" +#20102=* +lines(#20102,#20101,"expr + expr","") +#20103=@"loc,{#10000},5,15,5,25" +locations_default(#20103,#10000,5,15,5,25) +hasLocation(#20102,#20103) +numlines(#20101,1,1,0) +#20104=* +tokeninfo(#20104,6,#20101,0,"expr") +#20105=@"loc,{#10000},5,15,5,18" +locations_default(#20105,#10000,5,15,5,18) +hasLocation(#20104,#20105) +#20106=* +tokeninfo(#20106,8,#20101,1,"+") +#20107=@"loc,{#10000},5,20,5,20" +locations_default(#20107,#10000,5,20,5,20) +hasLocation(#20106,#20107) +#20108=* +tokeninfo(#20108,6,#20101,2,"expr") +#20109=@"loc,{#10000},5,22,5,25" +locations_default(#20109,#10000,5,22,5,25) +hasLocation(#20108,#20109) +#20110=* +tokeninfo(#20110,0,#20101,3,"") +#20111=@"loc,{#10000},5,26,5,25" +locations_default(#20111,#10000,5,26,5,25) +hasLocation(#20110,#20111) +toplevels(#20101,4) +hasLocation(#20101,#20103) +#20112=@"module;{#10000},5,15" +scopes(#20112,3) +scopenodes(#20101,#20112) +scopenesting(#20112,#20000) +is_module(#20101) #20113=* -exprs(#20113,34,#20112,0,"expr + expr") -hasLocation(#20113,#20102) -enclosing_stmt(#20113,#20112) -expr_containers(#20113,#20100) +stmts(#20113,2,#20101,0,"expr + expr") +hasLocation(#20113,#20103) +stmt_containers(#20113,#20101) #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};{#20111}" -variables(#20115,"expr",#20111) -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) +exprs(#20114,34,#20113,0,"expr + expr") +hasLocation(#20114,#20103) +enclosing_stmt(#20114,#20113) +expr_containers(#20114,#20101) +#20115=* +exprs(#20115,79,#20114,0,"expr") +hasLocation(#20115,#20105) +enclosing_stmt(#20115,#20113) +expr_containers(#20115,#20101) +literals("expr","expr",#20115) +#20116=@"var;{expr};{#20112}" +variables(#20116,"expr",#20112) +bind(#20115,#20116) #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) +exprs(#20117,79,#20114,1,"expr") +hasLocation(#20117,#20109) +enclosing_stmt(#20117,#20113) +expr_containers(#20117,#20101) +literals("expr","expr",#20117) +bind(#20117,#20116) +#20118=* +entry_cfg_node(#20118,#20101) +#20119=@"loc,{#10000},5,15,5,14" +locations_default(#20119,#10000,5,15,5,14) +hasLocation(#20118,#20119) #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,4) -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) +exit_cfg_node(#20120,#20101) +hasLocation(#20120,#20111) +successor(#20113,#20115) +successor(#20117,#20114) +successor(#20115,#20117) +successor(#20114,#20120) +successor(#20118,#20113) +toplevel_parent_xml_node(#20101,#20100) +#20121=* +#20122=@"script;{#10000},6,14" +#20123=* +lines(#20123,#20122,"expr!","") +#20124=@"loc,{#10000},6,14,6,18" +locations_default(#20124,#10000,6,14,6,18) +hasLocation(#20123,#20124) +numlines(#20122,1,1,0) +#20125=* +tokeninfo(#20125,6,#20122,0,"expr") +#20126=@"loc,{#10000},6,14,6,17" +locations_default(#20126,#10000,6,14,6,17) +hasLocation(#20125,#20126) +#20127=* +tokeninfo(#20127,8,#20122,1,"!") +#20128=@"loc,{#10000},6,18,6,18" +locations_default(#20128,#10000,6,18,6,18) +hasLocation(#20127,#20128) +#20129=* +tokeninfo(#20129,0,#20122,2,"") +#20130=@"loc,{#10000},6,19,6,18" +locations_default(#20130,#10000,6,19,6,18) +hasLocation(#20129,#20130) +toplevels(#20122,4) +hasLocation(#20122,#20124) +#20131=@"module;{#10000},6,14" +scopes(#20131,3) +scopenodes(#20122,#20131) +scopenesting(#20131,#20000) +is_module(#20122) #20132=* -exprs(#20132,105,#20131,0,"expr!") -hasLocation(#20132,#20123) -enclosing_stmt(#20132,#20131) -expr_containers(#20132,#20121) +stmts(#20132,2,#20122,0,"expr!") +hasLocation(#20132,#20124) +stmt_containers(#20132,#20122) #20133=* -exprs(#20133,79,#20132,0,"expr") -hasLocation(#20133,#20125) -enclosing_stmt(#20133,#20131) -expr_containers(#20133,#20121) -literals("expr","expr",#20133) -#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,#20137) -successor(#20135,#20131) +exprs(#20133,105,#20132,0,"expr!") +hasLocation(#20133,#20124) +enclosing_stmt(#20133,#20132) +expr_containers(#20133,#20122) +#20134=* +exprs(#20134,79,#20133,0,"expr") +hasLocation(#20134,#20126) +enclosing_stmt(#20134,#20132) +expr_containers(#20134,#20122) +literals("expr","expr",#20134) +#20135=@"var;{expr};{#20131}" +variables(#20135,"expr",#20131) +bind(#20134,#20135) +#20136=* +entry_cfg_node(#20136,#20122) +#20137=@"loc,{#10000},6,14,6,13" +locations_default(#20137,#10000,6,14,6,13) +hasLocation(#20136,#20137) #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=* -stmts(#20151,2,#20139,0,"expr?.bar") -hasLocation(#20151,#20141) -stmt_containers(#20151,#20139) +exit_cfg_node(#20138,#20122) +hasLocation(#20138,#20130) +successor(#20132,#20134) +successor(#20134,#20133) +successor(#20133,#20138) +successor(#20136,#20132) +toplevel_parent_xml_node(#20122,#20121) +#20139=* +#20140=@"script;{#10000},7,14" +#20141=* +lines(#20141,#20140,"expr?.bar","") +#20142=@"loc,{#10000},7,14,7,22" +locations_default(#20142,#10000,7,14,7,22) +hasLocation(#20141,#20142) +numlines(#20140,1,1,0) +#20143=* +tokeninfo(#20143,6,#20140,0,"expr") +#20144=@"loc,{#10000},7,14,7,17" +locations_default(#20144,#10000,7,14,7,17) +hasLocation(#20143,#20144) +#20145=* +tokeninfo(#20145,8,#20140,1,"?.") +#20146=@"loc,{#10000},7,18,7,19" +locations_default(#20146,#10000,7,18,7,19) +hasLocation(#20145,#20146) +#20147=* +tokeninfo(#20147,6,#20140,2,"bar") +#20148=@"loc,{#10000},7,20,7,22" +locations_default(#20148,#10000,7,20,7,22) +hasLocation(#20147,#20148) +#20149=* +tokeninfo(#20149,0,#20140,3,"") +#20150=@"loc,{#10000},7,23,7,22" +locations_default(#20150,#10000,7,23,7,22) +hasLocation(#20149,#20150) +toplevels(#20140,4) +hasLocation(#20140,#20142) +#20151=@"module;{#10000},7,14" +scopes(#20151,3) +scopenodes(#20140,#20151) +scopenesting(#20151,#20000) +is_module(#20140) #20152=* -exprs(#20152,14,#20151,0,"expr?.bar") -hasLocation(#20152,#20141) -enclosing_stmt(#20152,#20151) -expr_containers(#20152,#20139) +stmts(#20152,2,#20140,0,"expr?.bar") +hasLocation(#20152,#20142) +stmt_containers(#20152,#20140) #20153=* -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) +exprs(#20153,14,#20152,0,"expr?.bar") +hasLocation(#20153,#20142) +enclosing_stmt(#20153,#20152) +expr_containers(#20153,#20140) +#20154=* +exprs(#20154,79,#20153,0,"expr") +hasLocation(#20154,#20144) +enclosing_stmt(#20154,#20152) +expr_containers(#20154,#20140) +literals("expr","expr",#20154) +#20155=@"var;{expr};{#20151}" +variables(#20155,"expr",#20151) +bind(#20154,#20155) #20156=* -entry_cfg_node(#20156,#20139) -#20157=@"loc,{#10000},7,14,7,13" -locations_default(#20157,#10000,7,14,7,13) -hasLocation(#20156,#20157) -#20158=* -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) +exprs(#20156,0,#20153,1,"bar") +hasLocation(#20156,#20148) +enclosing_stmt(#20156,#20152) +expr_containers(#20156,#20140) +literals("bar","bar",#20156) +isOptionalChaining(#20153) +#20157=* +entry_cfg_node(#20157,#20140) +#20158=@"loc,{#10000},7,14,7,13" +locations_default(#20158,#10000,7,14,7,13) +hasLocation(#20157,#20158) #20159=* -toplevel_parent_xml_node(#20139,#20159) +exit_cfg_node(#20159,#20140) +hasLocation(#20159,#20150) +successor(#20152,#20154) +successor(#20156,#20153) +successor(#20154,#20156) +successor(#20153,#20159) +successor(#20154,#20159) +successor(#20157,#20152) +toplevel_parent_xml_node(#20140,#20139) #20160=* xmlChars(#20160," ",#10000,0,0,#10000) @@ -568,28 +568,28 @@ xmlElements(#20168,"foo",#10000,5,#10000) #20169=@"loc,{#10000},7,2,7,26" locations_default(#20169,#10000,7,2,7,26) xmllocations(#20168,#20169) -xmlAttrs(#20159,#20168,"[baz]","expr?.bar",0,#10000) +xmlAttrs(#20139,#20168,"[baz]","expr?.bar",0,#10000) #20170=@"loc,{#10000},7,7,7,23" locations_default(#20170,#10000,7,7,7,23) -xmllocations(#20159,#20170) +xmllocations(#20139,#20170) #20171=* xmlElements(#20171,"foo",#10000,3,#10000) #20172=@"loc,{#10000},6,2,6,22" locations_default(#20172,#10000,6,2,6,22) xmllocations(#20171,#20172) -xmlAttrs(#20138,#20171,"[baz]","expr!",0,#10000) +xmlAttrs(#20121,#20171,"[baz]","expr!",0,#10000) #20173=@"loc,{#10000},6,7,6,19" locations_default(#20173,#10000,6,7,6,19) -xmllocations(#20138,#20173) +xmllocations(#20121,#20173) #20174=* xmlElements(#20174,"foo",#10000,1,#10000) #20175=@"loc,{#10000},5,2,5,28" locations_default(#20175,#10000,5,2,5,28) xmllocations(#20174,#20175) -xmlAttrs(#20120,#20174,"[prop]","expr + expr",0,#10000) +xmlAttrs(#20100,#20174,"[prop]","expr + expr",0,#10000) #20176=@"loc,{#10000},5,7,5,26" locations_default(#20176,#10000,5,7,5,26) -xmllocations(#20120,#20176) +xmllocations(#20100,#20176) xml_element_parent_expression(#20174,#20097,0) xml_element_parent_expression(#20171,#20097,1) xml_element_parent_expression(#20168,#20097,2) diff --git a/javascript/extractor/tests/node/output/trap/tst.html.trap b/javascript/extractor/tests/node/output/trap/tst.html.trap index a647c518a44..7f045ba240a 100644 --- a/javascript/extractor/tests/node/output/trap/tst.html.trap +++ b/javascript/extractor/tests/node/output/trap/tst.html.trap @@ -8,86 +8,86 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},6,13" -#20002=* -lines(#20002,#20001,"var x = 42;","") -#20003=@"loc,{#10000},6,13,6,23" -locations_default(#20003,#10000,6,13,6,23) -hasLocation(#20002,#20003) -numlines(#20001,1,1,0) -#20004=* -tokeninfo(#20004,7,#20001,0,"var") -#20005=@"loc,{#10000},6,13,6,15" -locations_default(#20005,#10000,6,13,6,15) -hasLocation(#20004,#20005) -#20006=* -tokeninfo(#20006,6,#20001,1,"x") -#20007=@"loc,{#10000},6,17,6,17" -locations_default(#20007,#10000,6,17,6,17) -hasLocation(#20006,#20007) -#20008=* -tokeninfo(#20008,8,#20001,2,"=") -#20009=@"loc,{#10000},6,19,6,19" -locations_default(#20009,#10000,6,19,6,19) -hasLocation(#20008,#20009) -#20010=* -tokeninfo(#20010,3,#20001,3,"42") -#20011=@"loc,{#10000},6,21,6,22" -locations_default(#20011,#10000,6,21,6,22) -hasLocation(#20010,#20011) -#20012=* -tokeninfo(#20012,8,#20001,4,";") -#20013=@"loc,{#10000},6,23,6,23" -locations_default(#20013,#10000,6,23,6,23) -hasLocation(#20012,#20013) -#20014=* -tokeninfo(#20014,0,#20001,5,"") -#20015=@"loc,{#10000},6,24,6,23" -locations_default(#20015,#10000,6,24,6,23) -hasLocation(#20014,#20015) -toplevels(#20001,2) -hasLocation(#20001,#20003) -#20016=@"var;{x};{#20000}" -variables(#20016,"x",#20000) -#20017=* -stmts(#20017,18,#20001,0,"var x = 42;") -hasLocation(#20017,#20003) -stmt_containers(#20017,#20001) +#20001=* +#20002=@"script;{#10000},6,13" +#20003=* +lines(#20003,#20002,"var x = 42;","") +#20004=@"loc,{#10000},6,13,6,23" +locations_default(#20004,#10000,6,13,6,23) +hasLocation(#20003,#20004) +numlines(#20002,1,1,0) +#20005=* +tokeninfo(#20005,7,#20002,0,"var") +#20006=@"loc,{#10000},6,13,6,15" +locations_default(#20006,#10000,6,13,6,15) +hasLocation(#20005,#20006) +#20007=* +tokeninfo(#20007,6,#20002,1,"x") +#20008=@"loc,{#10000},6,17,6,17" +locations_default(#20008,#10000,6,17,6,17) +hasLocation(#20007,#20008) +#20009=* +tokeninfo(#20009,8,#20002,2,"=") +#20010=@"loc,{#10000},6,19,6,19" +locations_default(#20010,#10000,6,19,6,19) +hasLocation(#20009,#20010) +#20011=* +tokeninfo(#20011,3,#20002,3,"42") +#20012=@"loc,{#10000},6,21,6,22" +locations_default(#20012,#10000,6,21,6,22) +hasLocation(#20011,#20012) +#20013=* +tokeninfo(#20013,8,#20002,4,";") +#20014=@"loc,{#10000},6,23,6,23" +locations_default(#20014,#10000,6,23,6,23) +hasLocation(#20013,#20014) +#20015=* +tokeninfo(#20015,0,#20002,5,"") +#20016=@"loc,{#10000},6,24,6,23" +locations_default(#20016,#10000,6,24,6,23) +hasLocation(#20015,#20016) +toplevels(#20002,2) +hasLocation(#20002,#20004) +#20017=@"var;{x};{#20000}" +variables(#20017,"x",#20000) #20018=* -exprs(#20018,64,#20017,0,"x = 42") -#20019=@"loc,{#10000},6,17,6,22" -locations_default(#20019,#10000,6,17,6,22) -hasLocation(#20018,#20019) -enclosing_stmt(#20018,#20017) -expr_containers(#20018,#20001) -#20020=* -exprs(#20020,78,#20018,0,"x") -hasLocation(#20020,#20007) -enclosing_stmt(#20020,#20017) -expr_containers(#20020,#20001) -literals("x","x",#20020) -decl(#20020,#20016) +stmts(#20018,18,#20002,0,"var x = 42;") +hasLocation(#20018,#20004) +stmt_containers(#20018,#20002) +#20019=* +exprs(#20019,64,#20018,0,"x = 42") +#20020=@"loc,{#10000},6,17,6,22" +locations_default(#20020,#10000,6,17,6,22) +hasLocation(#20019,#20020) +enclosing_stmt(#20019,#20018) +expr_containers(#20019,#20002) #20021=* -exprs(#20021,3,#20018,1,"42") -hasLocation(#20021,#20011) -enclosing_stmt(#20021,#20017) -expr_containers(#20021,#20001) -literals("42","42",#20021) +exprs(#20021,78,#20019,0,"x") +hasLocation(#20021,#20008) +enclosing_stmt(#20021,#20018) +expr_containers(#20021,#20002) +literals("x","x",#20021) +decl(#20021,#20017) #20022=* -entry_cfg_node(#20022,#20001) -#20023=@"loc,{#10000},6,13,6,12" -locations_default(#20023,#10000,6,13,6,12) -hasLocation(#20022,#20023) -#20024=* -exit_cfg_node(#20024,#20001) -hasLocation(#20024,#20015) -successor(#20017,#20020) -successor(#20021,#20018) -successor(#20020,#20021) -successor(#20018,#20024) -successor(#20022,#20017) +exprs(#20022,3,#20019,1,"42") +hasLocation(#20022,#20012) +enclosing_stmt(#20022,#20018) +expr_containers(#20022,#20002) +literals("42","42",#20022) +#20023=* +entry_cfg_node(#20023,#20002) +#20024=@"loc,{#10000},6,13,6,12" +locations_default(#20024,#10000,6,13,6,12) +hasLocation(#20023,#20024) #20025=* -toplevel_parent_xml_node(#20001,#20025) +exit_cfg_node(#20025,#20002) +hasLocation(#20025,#20016) +successor(#20018,#20021) +successor(#20022,#20019) +successor(#20021,#20022) +successor(#20019,#20025) +successor(#20023,#20018) +toplevel_parent_xml_node(#20002,#20001) #20026=* xmlElements(#20026,"html",#10000,0,#10000) #20027=@"loc,{#10000},1,1,8,7" @@ -103,10 +103,10 @@ 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) +xmlAttrs(#20001,#20030,"onclick","var x = 42;",0,#10000) #20032=@"loc,{#10000},6,4,6,24" locations_default(#20032,#10000,6,4,6,24) -xmllocations(#20025,#20032) +xmllocations(#20001,#20032) #20033=* xmlElements(#20033,"head",#20026,0,#10000) #20034=@"loc,{#10000},2,1,4,7" diff --git a/javascript/extractor/tests/shebang/output/trap/tst.html.trap b/javascript/extractor/tests/shebang/output/trap/tst.html.trap index 4c153f4d397..08d0f35bc2f 100644 --- a/javascript/extractor/tests/shebang/output/trap/tst.html.trap +++ b/javascript/extractor/tests/shebang/output/trap/tst.html.trap @@ -8,43 +8,43 @@ locations_default(#10002,#10000,0,0,0,0) hasLocation(#10000,#10002) #20000=@"global_scope" scopes(#20000,0) -#20001=@"script;{#10000},3,17" -toplevels(#20001,1) -#20002=@"loc,{#10000},3,17,3,17" -locations_default(#20002,#10000,3,17,3,17) -hasLocation(#20001,#20002) -#20003=* -js_parse_errors(#20003,#20001,"Error: Unexpected token","#!/usr/bin/node +#20001=* +#20002=@"script;{#10000},3,17" +toplevels(#20002,1) +#20003=@"loc,{#10000},3,17,3,17" +locations_default(#20003,#10000,3,17,3,17) +hasLocation(#20002,#20003) +#20004=* +js_parse_errors(#20004,#20002,"Error: Unexpected token","#!/usr/bin/node ") -#20004=@"loc,{#10000},4,1,4,1" -locations_default(#20004,#10000,4,1,4,1) -hasLocation(#20003,#20004) -#20005=* -lines(#20005,#20001,""," +#20005=@"loc,{#10000},4,1,4,1" +locations_default(#20005,#10000,4,1,4,1) +hasLocation(#20004,#20005) +#20006=* +lines(#20006,#20002,""," ") -#20006=@"loc,{#10000},3,17,3,16" -locations_default(#20006,#10000,3,17,3,16) -hasLocation(#20005,#20006) -#20007=* -lines(#20007,#20001,"#!/usr/bin/node"," +#20007=@"loc,{#10000},3,17,3,16" +locations_default(#20007,#10000,3,17,3,16) +hasLocation(#20006,#20007) +#20008=* +lines(#20008,#20002,"#!/usr/bin/node"," ") -#20008=@"loc,{#10000},4,1,4,15" -locations_default(#20008,#10000,4,1,4,15) -hasLocation(#20007,#20008) -#20009=* -lines(#20009,#20001,"// shebang in HTML is not OK"," +#20009=@"loc,{#10000},4,1,4,15" +locations_default(#20009,#10000,4,1,4,15) +hasLocation(#20008,#20009) +#20010=* +lines(#20010,#20002,"// shebang in HTML is not OK"," ") -#20010=@"loc,{#10000},5,1,5,28" -locations_default(#20010,#10000,5,1,5,28) -hasLocation(#20009,#20010) -#20011=* -lines(#20011,#20001," ","") -#20012=@"loc,{#10000},6,1,6,8" -locations_default(#20012,#10000,6,1,6,8) -hasLocation(#20011,#20012) -numlines(#20001,4,0,0) -#20013=* -toplevel_parent_xml_node(#20001,#20013) +#20011=@"loc,{#10000},5,1,5,28" +locations_default(#20011,#10000,5,1,5,28) +hasLocation(#20010,#20011) +#20012=* +lines(#20012,#20002," ","") +#20013=@"loc,{#10000},6,1,6,8" +locations_default(#20013,#10000,6,1,6,8) +hasLocation(#20012,#20013) +numlines(#20002,4,0,0) +toplevel_parent_xml_node(#20002,#20001) #20014=* xmlElements(#20014,"html",#10000,0,#10000) #20015=@"loc,{#10000},1,1,10,7" @@ -60,9 +60,9 @@ 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) +xmlElements(#20001,"script",#20018,0,#10000) #20020=@"loc,{#10000},3,9,6,17" locations_default(#20020,#10000,3,9,6,17) -xmllocations(#20013,#20020) +xmllocations(#20001,#20020) numlines(#10000,10,0,0) filetype(#10000,"html") From 2da40b8b0760766ba72222e7ac4b545ebd67cd6f Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 11 Aug 2021 14:31:06 +0200 Subject: [PATCH 224/429] JS: Fix some performance issues --- .../semmle/javascript/frameworks/Templating.qll | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index c27750254a3..412fceee5aa 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -125,6 +125,7 @@ module Templating { /** * Gets the innermost JavaScript expression containing this template tag, if any. */ + pragma[nomagic] Expr getEnclosingExpr() { expr_contains_template_tag_location(result, getLocation()) } } @@ -315,12 +316,17 @@ module Templating { ) } + pragma[nomagic] + private Folder getFolder() { + result = getFile().getParentContainer() + } + /** Gets the template file referenced by this node. */ final TemplateFile getTemplateFile() { result = this.getValue() .(TemplateFileReferenceString) - .getTemplateFile(getFile().getParentContainer()) + .getTemplateFile(getFolder()) } } @@ -377,7 +383,12 @@ module Templating { DefaultTemplateReferenceString() { this = r.getValue().replaceAll("\\", "/") } - override Folder getContextFolder() { result = r.getFile().getParentContainer() } + pragma[nomagic] // Stop optimizer from trying to share the 'getParentContainer' join + private Folder getFileReferenceFolder() { + result = pragma[only_bind_out](r).getFile().getParentContainer() + } + + override Folder getContextFolder() { result = getFileReferenceFolder() } } /** The `X` in a path of form `../X`, treated as a separate path string with a different context folder. */ From bd3a24d56812763fc6bbf33bf9aa215c7e0883b8 Mon Sep 17 00:00:00 2001 From: yo-h <55373593+yo-h@users.noreply.github.com> Date: Wed, 11 Aug 2021 20:03:32 -0400 Subject: [PATCH 225/429] Java: add `org.json` package to known frameworks --- java/documentation/library-coverage/frameworks.csv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/documentation/library-coverage/frameworks.csv b/java/documentation/library-coverage/frameworks.csv index bd5feddb8ed..28493067fa7 100644 --- a/java/documentation/library-coverage/frameworks.csv +++ b/java/documentation/library-coverage/frameworks.csv @@ -1,11 +1,12 @@ Framework name,URL,Package prefixes Java Standard Library,,java.* Java extensions,,javax.* jakarta.* -Google Guava,https://guava.dev/,com.google.common.* Apache Commons Collections,https://commons.apache.org/proper/commons-collections/,org.apache.commons.collections org.apache.commons.collections4 Apache Commons IO,https://commons.apache.org/proper/commons-io/,org.apache.commons.io Apache Commons Lang,https://commons.apache.org/proper/commons-lang/,org.apache.commons.lang3 Apache Commons Text,https://commons.apache.org/proper/commons-text/,org.apache.commons.text Apache HttpComponents,https://hc.apache.org/,org.apache.hc.core5.* org.apache.http Android,,android.* +Google Guava,https://guava.dev/,com.google.common.* +JSON-java,https://github.com/stleary/JSON-java,org.json Spring,https://spring.io/,org.springframework.* From f6da0305721c32b86c8acd84d218fee1edf9c4c7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 12 Aug 2021 09:30:18 +0200 Subject: [PATCH 226/429] JS: Migrate to *Query.qll convention --- .../ExternalAPIsUsedWithUntrustedData.ql | 2 +- .../CWE-020/UntrustedDataToExternalAPI.ql | 2 +- .../ql/src/Security/CWE-022/TaintedPath.ql | 2 +- javascript/ql/src/Security/CWE-022/ZipSlip.ql | 2 +- .../CWE-073/TemplateObjectInjection.ql | 2 +- .../src/Security/CWE-078/CommandInjection.ql | 2 +- .../CWE-078/IndirectCommandInjection.ql | 2 +- .../ShellCommandInjectionFromEnvironment.ql | 2 +- .../CWE-078/UnsafeShellCommandConstruction.ql | 2 +- .../ql/src/Security/CWE-079/ExceptionXss.ql | 2 +- .../ql/src/Security/CWE-079/ReflectedXss.ql | 2 +- .../ql/src/Security/CWE-079/StoredXss.ql | 2 +- .../CWE-079/UnsafeHtmlConstruction.ql | 2 +- .../Security/CWE-079/UnsafeJQueryPlugin.ql | 2 +- javascript/ql/src/Security/CWE-079/Xss.ql | 2 +- .../ql/src/Security/CWE-079/XssThroughDom.ql | 2 +- .../ql/src/Security/CWE-094/CodeInjection.ql | 2 +- .../CWE-094/ImproperCodeSanitization.ql | 2 +- .../CWE-094/UnsafeDynamicMethodAccess.ql | 2 +- .../IncompleteHtmlAttributeSanitization.ql | 2 +- .../ql/src/Security/CWE-117/LogInjection.ql | 2 +- .../Security/CWE-134/TaintedFormatString.ql | 2 +- .../src/Security/CWE-200/FileAccessToHttp.ql | 2 +- .../src/Security/CWE-201/PostMessageStar.ql | 2 +- .../Security/CWE-209/StackTraceExposure.ql | 2 +- .../src/Security/CWE-312/BuildArtifactLeak.ql | 2 +- .../src/Security/CWE-312/CleartextLogging.ql | 2 +- .../src/Security/CWE-312/CleartextStorage.ql | 2 +- .../Security/CWE-327/BrokenCryptoAlgorithm.ql | 2 +- .../Security/CWE-338/InsecureRandomness.ql | 2 +- .../CorsMisconfigurationForCredentials.ql | 2 +- .../CWE-400/DeepObjectResourceExhaustion.ql | 2 +- .../CWE-400/RemotePropertyInjection.ql | 2 +- .../Security/CWE-502/UnsafeDeserialization.ql | 2 +- .../CWE-506/HardcodedDataInterpretedAsCode.ql | 2 +- .../Security/CWE-601/ClientSideUrlRedirect.ql | 2 +- .../Security/CWE-601/ServerSideUrlRedirect.ql | 2 +- javascript/ql/src/Security/CWE-611/Xxe.ql | 2 +- .../HostHeaderPoisoningInEmailGeneration.ql | 2 +- .../ql/src/Security/CWE-643/XpathInjection.ql | 2 +- .../src/Security/CWE-730/RegExpInjection.ql | 2 +- .../CWE-754/UnvalidatedDynamicMethodCall.ql | 2 +- javascript/ql/src/Security/CWE-776/XmlBomb.ql | 2 +- .../Security/CWE-798/HardcodedCredentials.ql | 2 +- .../src/Security/CWE-807/ConditionalBypass.ql | 2 +- .../CWE-807/DifferentKindsComparisonBypass.ql | 2 +- .../src/Security/CWE-829/InsecureDownload.ql | 2 +- .../Security/CWE-834/LoopBoundInjection.ql | 2 +- .../TypeConfusionThroughParameterTampering.ql | 2 +- .../src/Security/CWE-912/HttpToFileAccess.ql | 2 +- .../CWE-915/PrototypePollutingAssignment.ql | 2 +- .../CWE-915/PrototypePollutingMergeCall.ql | 2 +- .../CWE-916/InsufficientPasswordHash.ql | 2 +- .../ql/src/Security/CWE-918/RequestForgery.ql | 2 +- .../dataflow/BrokenCryptoAlgorithm.qll | 37 +-- .../dataflow/BrokenCryptoAlgorithmQuery.qll | 33 +++ .../security/dataflow/BuildArtifactLeak.qll | 46 +--- .../dataflow/BuildArtifactLeakQuery.qll | 37 +++ .../security/dataflow/CleartextLogging.qll | 46 +--- .../dataflow/CleartextLoggingQuery.qll | 42 ++++ .../security/dataflow/CleartextStorage.qll | 34 +-- .../dataflow/CleartextStorageQuery.qll | 30 +++ .../dataflow/ClientSideUrlRedirect.qll | 70 +----- .../dataflow/ClientSideUrlRedirectQuery.qll | 67 ++++++ .../security/dataflow/CodeInjection.qll | 36 +-- .../security/dataflow/CodeInjectionQuery.qll | 32 +++ .../security/dataflow/CommandInjection.qll | 39 +--- .../dataflow/CommandInjectionQuery.qll | 35 +++ .../security/dataflow/ConditionalBypass.qll | 36 +-- .../dataflow/ConditionalBypassQuery.qll | 32 +++ .../CorsMisconfigurationForCredentials.qll | 36 +-- ...orsMisconfigurationForCredentialsQuery.qll | 32 +++ .../dataflow/DeepObjectResourceExhaustion.qll | 41 +--- .../DeepObjectResourceExhaustionQuery.qll | 34 +++ .../DifferentKindsComparisonBypass.qll | 54 +---- .../DifferentKindsComparisonBypassQuery.qll | 51 +++++ .../security/dataflow/DomBasedXss.qll | 97 +------- .../security/dataflow/DomBasedXssQuery.qll | 93 ++++++++ .../security/dataflow/ExceptionXss.qll | 163 +------------- .../security/dataflow/ExceptionXssQuery.qll | 158 +++++++++++++ .../ExternalAPIUsedWithUntrustedData.qll | 107 +-------- .../ExternalAPIUsedWithUntrustedDataQuery.qll | 99 ++++++++ .../security/dataflow/FileAccessToHttp.qll | 39 +--- .../dataflow/FileAccessToHttpQuery.qll | 35 +++ .../dataflow/HardcodedCredentials.qll | 38 +--- .../dataflow/HardcodedCredentialsQuery.qll | 34 +++ .../HardcodedDataInterpretedAsCode.qll | 34 +-- .../HardcodedDataInterpretedAsCodeQuery.qll | 30 +++ .../HostHeaderPoisoningInEmailGeneration.qll | 27 +-- ...tHeaderPoisoningInEmailGenerationQuery.qll | 24 ++ .../security/dataflow/HttpToFileAccess.qll | 30 +-- .../dataflow/HttpToFileAccessQuery.qll | 26 +++ .../dataflow/ImproperCodeSanitization.qll | 31 +-- .../ImproperCodeSanitizationQuery.qll | 24 ++ .../IncompleteHtmlAttributeSanitization.qll | 59 +---- ...completeHtmlAttributeSanitizationQuery.qll | 55 +++++ .../dataflow/IndirectCommandInjection.qll | 39 +--- .../IndirectCommandInjectionQuery.qll | 35 +++ .../security/dataflow/InsecureDownload.qll | 41 +--- .../dataflow/InsecureDownloadQuery.qll | 34 +++ .../security/dataflow/InsecureRandomness.qll | 43 +--- .../dataflow/InsecureRandomnessQuery.qll | 39 ++++ .../dataflow/InsufficientPasswordHash.qll | 37 +-- .../InsufficientPasswordHashQuery.qll | 33 +++ .../security/dataflow/LogInjection.qll | 78 +------ .../security/dataflow/LogInjectionQuery.qll | 72 ++++++ .../security/dataflow/LoopBoundInjection.qll | 43 +--- .../dataflow/LoopBoundInjectionQuery.qll | 40 ++++ .../security/dataflow/NosqlInjection.qll | 56 +---- .../security/dataflow/NosqlInjectionQuery.qll | 53 +++++ .../security/dataflow/PostMessageStar.qll | 69 +----- .../dataflow/PostMessageStarQuery.qll | 65 ++++++ .../dataflow/PrototypePollutingAssignment.qll | 211 +----------------- .../PrototypePollutingAssignmentQuery.qll | 200 +++++++++++++++++ .../security/dataflow/PrototypePollution.qll | 54 +---- .../dataflow/PrototypePollutionQuery.qll | 53 +++++ .../security/dataflow/ReflectedXss.qll | 31 +-- .../security/dataflow/ReflectedXssQuery.qll | 27 +++ .../security/dataflow/RegExpInjection.qll | 31 +-- .../dataflow/RegExpInjectionQuery.qll | 27 +++ .../dataflow/RemotePropertyInjection.qll | 33 +-- .../dataflow/RemotePropertyInjectionQuery.qll | 29 +++ .../security/dataflow/RequestForgery.qll | 39 +--- .../security/dataflow/RequestForgeryQuery.qll | 36 +++ .../dataflow/ServerSideUrlRedirect.qll | 40 +--- .../dataflow/ServerSideUrlRedirectQuery.qll | 38 ++++ .../ShellCommandInjectionFromEnvironment.qll | 35 +-- ...llCommandInjectionFromEnvironmentQuery.qll | 31 +++ .../security/dataflow/SqlInjection.qll | 31 +-- .../security/dataflow/SqlInjectionQuery.qll | 27 +++ .../security/dataflow/StackTraceExposure.qll | 39 +--- .../dataflow/StackTraceExposureQuery.qll | 35 +++ .../security/dataflow/StoredXss.qll | 41 +--- .../security/dataflow/StoredXssQuery.qll | 37 +++ .../security/dataflow/TaintedFormatString.qll | 32 +-- .../dataflow/TaintedFormatStringQuery.qll | 29 +++ .../security/dataflow/TaintedPath.qll | 55 +---- .../security/dataflow/TaintedPathQuery.qll | 51 +++++ .../dataflow/TemplateObjectInjection.qll | 46 +--- .../dataflow/TemplateObjectInjectionQuery.qll | 39 ++++ ...TypeConfusionThroughParameterTampering.qll | 35 +-- ...onfusionThroughParameterTamperingQuery.qll | 30 +++ .../dataflow/UnsafeDeserialization.qll | 30 +-- .../dataflow/UnsafeDeserializationQuery.qll | 27 +++ .../dataflow/UnsafeDynamicMethodAccess.qll | 75 +------ .../UnsafeDynamicMethodAccessQuery.qll | 72 ++++++ .../dataflow/UnsafeHtmlConstruction.qll | 49 +--- .../dataflow/UnsafeHtmlConstructionQuery.qll | 42 ++++ .../security/dataflow/UnsafeJQueryPlugin.qll | 87 +------- .../dataflow/UnsafeJQueryPluginQuery.qll | 83 +++++++ .../UnsafeShellCommandConstruction.qll | 46 +--- .../UnsafeShellCommandConstructionQuery.qll | 39 ++++ .../dataflow/UnvalidatedDynamicMethodCall.qll | 64 +----- .../UnvalidatedDynamicMethodCallQuery.qll | 62 +++++ .../javascript/security/dataflow/XmlBomb.qll | 31 +-- .../security/dataflow/XmlBombQuery.qll | 27 +++ .../security/dataflow/XpathInjection.qll | 31 +-- .../security/dataflow/XpathInjectionQuery.qll | 28 +++ .../security/dataflow/XssThroughDom.qll | 44 +--- .../security/dataflow/XssThroughDomQuery.qll | 37 +++ .../javascript/security/dataflow/Xxe.qll | 31 +-- .../javascript/security/dataflow/XxeQuery.qll | 27 +++ .../javascript/security/dataflow/ZipSlip.qll | 53 +---- .../security/dataflow/ZipSlipQuery.qll | 49 ++++ 164 files changed, 2831 insertions(+), 2633 deletions(-) create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll diff --git a/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql b/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql index 6f087448cfe..1d00abb104b 100644 --- a/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql +++ b/javascript/ql/src/Security/CWE-020/ExternalAPIsUsedWithUntrustedData.ql @@ -9,7 +9,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedData::ExternalAPIUsedWithUntrustedData +import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery from ExternalAPIUsedWithUntrustedData externalAPI select externalAPI, count(externalAPI.getUntrustedDataNode()) as numberOfUses, diff --git a/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql b/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql index 898e3b616cc..67d6f14f660 100644 --- a/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql +++ b/javascript/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql @@ -10,7 +10,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedData::ExternalAPIUsedWithUntrustedData +import semmle.javascript.security.dataflow.ExternalAPIUsedWithUntrustedDataQuery import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql index a9b197a28de..0c19137f38c 100644 --- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql +++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql @@ -16,7 +16,7 @@ */ import javascript -import semmle.javascript.security.dataflow.TaintedPath::TaintedPath +import semmle.javascript.security.dataflow.TaintedPathQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-022/ZipSlip.ql b/javascript/ql/src/Security/CWE-022/ZipSlip.ql index 8fcb9d7edaa..6daa4f01969 100644 --- a/javascript/ql/src/Security/CWE-022/ZipSlip.ql +++ b/javascript/ql/src/Security/CWE-022/ZipSlip.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ZipSlip::ZipSlip +import semmle.javascript.security.dataflow.ZipSlipQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-073/TemplateObjectInjection.ql b/javascript/ql/src/Security/CWE-073/TemplateObjectInjection.ql index 17d65433b54..ea4f0476484 100644 --- a/javascript/ql/src/Security/CWE-073/TemplateObjectInjection.ql +++ b/javascript/ql/src/Security/CWE-073/TemplateObjectInjection.ql @@ -13,7 +13,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.TemplateObjectInjection::TemplateObjectInjection +import semmle.javascript.security.dataflow.TemplateObjectInjectionQuery from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql index 59ebd7cc1ee..7bb57bfa6da 100644 --- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql +++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.CommandInjection::CommandInjection +import semmle.javascript.security.dataflow.CommandInjectionQuery import DataFlow::PathGraph from diff --git a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql index 31bf6cfdf85..eb29b56cac3 100644 --- a/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql +++ b/javascript/ql/src/Security/CWE-078/IndirectCommandInjection.ql @@ -16,7 +16,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.IndirectCommandInjection::IndirectCommandInjection +import semmle.javascript.security.dataflow.IndirectCommandInjectionQuery from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight where diff --git a/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql b/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql index a1c3f879961..b4bd735d493 100644 --- a/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql +++ b/javascript/ql/src/Security/CWE-078/ShellCommandInjectionFromEnvironment.ql @@ -15,7 +15,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironment::ShellCommandInjectionFromEnvironment +import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentQuery from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight, diff --git a/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql b/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql index a1dafda3921..b0b22a96704 100644 --- a/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql +++ b/javascript/ql/src/Security/CWE-078/UnsafeShellCommandConstruction.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.UnsafeShellCommandConstruction::UnsafeShellCommandConstruction +import semmle.javascript.security.dataflow.UnsafeShellCommandConstructionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode diff --git a/javascript/ql/src/Security/CWE-079/ExceptionXss.ql b/javascript/ql/src/Security/CWE-079/ExceptionXss.ql index 3723bfc99f8..c43206abb66 100644 --- a/javascript/ql/src/Security/CWE-079/ExceptionXss.ql +++ b/javascript/ql/src/Security/CWE-079/ExceptionXss.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ExceptionXss::ExceptionXss +import semmle.javascript.security.dataflow.ExceptionXssQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql index 9a102fcc57f..80ce5004935 100644 --- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql +++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss +import semmle.javascript.security.dataflow.ReflectedXssQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql index ed9aac39bd9..d5f28b28e55 100644 --- a/javascript/ql/src/Security/CWE-079/StoredXss.ql +++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.StoredXss::StoredXss +import semmle.javascript.security.dataflow.StoredXssQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-079/UnsafeHtmlConstruction.ql b/javascript/ql/src/Security/CWE-079/UnsafeHtmlConstruction.ql index cc85e07f61a..32a7dbe38b6 100644 --- a/javascript/ql/src/Security/CWE-079/UnsafeHtmlConstruction.ql +++ b/javascript/ql/src/Security/CWE-079/UnsafeHtmlConstruction.ql @@ -14,7 +14,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.UnsafeHtmlConstruction::UnsafeHtmlConstruction +import semmle.javascript.security.dataflow.UnsafeHtmlConstructionQuery from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode where cfg.hasFlowPath(source, sink) and sink.getNode() = sinkNode diff --git a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql index 24db75323df..0cd8312a8cd 100644 --- a/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql +++ b/javascript/ql/src/Security/CWE-079/UnsafeJQueryPlugin.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.UnsafeJQueryPlugin::UnsafeJQueryPlugin +import semmle.javascript.security.dataflow.UnsafeJQueryPluginQuery import DataFlow::PathGraph from diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql index 20aaa86e61a..ec0e2d2c9f1 100644 --- a/javascript/ql/src/Security/CWE-079/Xss.ql +++ b/javascript/ql/src/Security/CWE-079/Xss.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss +import semmle.javascript.security.dataflow.DomBasedXssQuery import DataFlow::PathGraph from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-079/XssThroughDom.ql b/javascript/ql/src/Security/CWE-079/XssThroughDom.ql index 3b15e6def61..87a76d82227 100644 --- a/javascript/ql/src/Security/CWE-079/XssThroughDom.ql +++ b/javascript/ql/src/Security/CWE-079/XssThroughDom.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.XssThroughDom::XssThroughDom +import semmle.javascript.security.dataflow.XssThroughDomQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql index 4c233079f44..2934107f1bb 100644 --- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql +++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.CodeInjection::CodeInjection +import semmle.javascript.security.dataflow.CodeInjectionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql b/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql index 7a8aedcb8c5..886c78b0161 100644 --- a/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql +++ b/javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ImproperCodeSanitization::ImproperCodeSanitization +import semmle.javascript.security.dataflow.ImproperCodeSanitizationQuery import DataFlow::PathGraph private import semmle.javascript.heuristics.HeuristicSinks private import semmle.javascript.security.dataflow.CodeInjectionCustomizations diff --git a/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql b/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql index 918f09496af..291fe71da7d 100644 --- a/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql +++ b/javascript/ql/src/Security/CWE-094/UnsafeDynamicMethodAccess.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccess::UnsafeDynamicMethodAccess +import semmle.javascript.security.dataflow.UnsafeDynamicMethodAccessQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql index ecfe0f63ea1..eec14ab7ba3 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteHtmlAttributeSanitization.ql @@ -16,7 +16,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.IncompleteHtmlAttributeSanitization::IncompleteHtmlAttributeSanitization +import semmle.javascript.security.dataflow.IncompleteHtmlAttributeSanitizationQuery import semmle.javascript.security.IncompleteBlacklistSanitizer /** diff --git a/javascript/ql/src/Security/CWE-117/LogInjection.ql b/javascript/ql/src/Security/CWE-117/LogInjection.ql index bcdd80ec543..2b9fff12e6f 100644 --- a/javascript/ql/src/Security/CWE-117/LogInjection.ql +++ b/javascript/ql/src/Security/CWE-117/LogInjection.ql @@ -13,7 +13,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.LogInjection::LogInjection +import semmle.javascript.security.dataflow.LogInjectionQuery from LogInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql index 00b7ea626e5..25cb62bd9b1 100644 --- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql +++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.TaintedFormatString::TaintedFormatString +import semmle.javascript.security.dataflow.TaintedFormatStringQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql index 928b22fdff4..481e7b4e898 100644 --- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql +++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.FileAccessToHttp::FileAccessToHttp +import semmle.javascript.security.dataflow.FileAccessToHttpQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-201/PostMessageStar.ql b/javascript/ql/src/Security/CWE-201/PostMessageStar.ql index cbb3df5cf5d..8884eaebf59 100644 --- a/javascript/ql/src/Security/CWE-201/PostMessageStar.ql +++ b/javascript/ql/src/Security/CWE-201/PostMessageStar.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.PostMessageStar::PostMessageStar +import semmle.javascript.security.dataflow.PostMessageStarQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql index a5e05eab0bb..49d14daf6c9 100644 --- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.StackTraceExposure::StackTraceExposure +import semmle.javascript.security.dataflow.StackTraceExposureQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql b/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql index e99c8076678..5a0d0bd5d5d 100644 --- a/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql +++ b/javascript/ql/src/Security/CWE-312/BuildArtifactLeak.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.BuildArtifactLeak::BuildArtifactLeak +import semmle.javascript.security.dataflow.BuildArtifactLeakQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql index 7a3626b4860..00916c4293d 100644 --- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql +++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.CleartextLogging::CleartextLogging +import semmle.javascript.security.dataflow.CleartextLoggingQuery import DataFlow::PathGraph /** diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql index ee9944c9b8d..39b14ef5aa8 100644 --- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql +++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.CleartextStorage::CleartextStorage +import semmle.javascript.security.dataflow.CleartextStorageQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql index 32625d62f77..1d64bf1be33 100644 --- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql +++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.BrokenCryptoAlgorithm::BrokenCryptoAlgorithm +import semmle.javascript.security.dataflow.BrokenCryptoAlgorithmQuery import semmle.javascript.security.SensitiveActions import DataFlow::PathGraph diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql index 66e86f65ffd..7de72260d33 100644 --- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql +++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.InsecureRandomness::InsecureRandomness +import semmle.javascript.security.dataflow.InsecureRandomnessQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql index 185533f93fb..1b0acebea15 100644 --- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql +++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentials::CorsMisconfigurationForCredentials +import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentialsQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql index 3e2ab24f70d..202cf6c591e 100644 --- a/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql +++ b/javascript/ql/src/Security/CWE-400/DeepObjectResourceExhaustion.ql @@ -12,7 +12,7 @@ import javascript import DataFlow::PathGraph -import semmle.javascript.security.dataflow.DeepObjectResourceExhaustion::DeepObjectResourceExhaustion +import semmle.javascript.security.dataflow.DeepObjectResourceExhaustionQuery from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node link, diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql index 4bfbbd85d23..724ad4104ef 100644 --- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql +++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.RemotePropertyInjection::RemotePropertyInjection +import semmle.javascript.security.dataflow.RemotePropertyInjectionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql index 89302f775f2..7423cb2f73d 100644 --- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql +++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.UnsafeDeserialization::UnsafeDeserialization +import semmle.javascript.security.dataflow.UnsafeDeserializationQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql b/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql index f0dfe833b06..8e5ef152f5f 100644 --- a/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql +++ b/javascript/ql/src/Security/CWE-506/HardcodedDataInterpretedAsCode.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.HardcodedDataInterpretedAsCode::HardcodedDataInterpretedAsCode +import semmle.javascript.security.dataflow.HardcodedDataInterpretedAsCodeQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql index 9e2987c966f..ae779121935 100644 --- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql +++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ClientSideUrlRedirect::ClientSideUrlRedirect +import semmle.javascript.security.dataflow.ClientSideUrlRedirectQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql index 3440d9ee405..0f610a2a584 100644 --- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql +++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ServerSideUrlRedirect::ServerSideUrlRedirect +import semmle.javascript.security.dataflow.ServerSideUrlRedirectQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql index b2733d068a2..01e518b6df7 100644 --- a/javascript/ql/src/Security/CWE-611/Xxe.ql +++ b/javascript/ql/src/Security/CWE-611/Xxe.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.Xxe::Xxe +import semmle.javascript.security.dataflow.XxeQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql index a2e24a9dd42..f4ee0b5239e 100644 --- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql +++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGeneration::HostHeaderPoisoningInEmailGeneration +import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGenerationQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql index 5aa4142cde7..58e96a6dfc1 100644 --- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql +++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.XpathInjection::XpathInjection +import semmle.javascript.security.dataflow.XpathInjectionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql index 4278df33f8a..8da2080d167 100644 --- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql +++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql @@ -14,7 +14,7 @@ */ import javascript -import semmle.javascript.security.dataflow.RegExpInjection::RegExpInjection +import semmle.javascript.security.dataflow.RegExpInjectionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql b/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql index 088d98bbbcb..c2841c5e902 100644 --- a/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql +++ b/javascript/ql/src/Security/CWE-754/UnvalidatedDynamicMethodCall.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCall::UnvalidatedDynamicMethodCall +import semmle.javascript.security.dataflow.UnvalidatedDynamicMethodCallQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql index 5320236421c..c340eee68cc 100644 --- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql +++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql @@ -13,7 +13,7 @@ */ import javascript -import semmle.javascript.security.dataflow.XmlBomb::XmlBomb +import semmle.javascript.security.dataflow.XmlBombQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql index e3df6c86973..d5087321cc0 100644 --- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql +++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql @@ -14,7 +14,7 @@ */ import javascript -private import semmle.javascript.security.dataflow.HardcodedCredentials::HardcodedCredentials +import semmle.javascript.security.dataflow.HardcodedCredentialsQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string value diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql index ee88eec03d2..f48f6fd56c3 100644 --- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql +++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.ConditionalBypass::ConditionalBypass +import semmle.javascript.security.dataflow.ConditionalBypassQuery import DataFlow::PathGraph /** diff --git a/javascript/ql/src/Security/CWE-807/DifferentKindsComparisonBypass.ql b/javascript/ql/src/Security/CWE-807/DifferentKindsComparisonBypass.ql index 20cd6446683..3e87f71b83c 100644 --- a/javascript/ql/src/Security/CWE-807/DifferentKindsComparisonBypass.ql +++ b/javascript/ql/src/Security/CWE-807/DifferentKindsComparisonBypass.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.DifferentKindsComparisonBypass::DifferentKindsComparisonBypass +import semmle.javascript.security.dataflow.DifferentKindsComparisonBypassQuery from DifferentKindsComparison cmp, DataFlow::Node lSource, DataFlow::Node rSource where diff --git a/javascript/ql/src/Security/CWE-829/InsecureDownload.ql b/javascript/ql/src/Security/CWE-829/InsecureDownload.ql index 41fea83ef1f..d1f27267477 100644 --- a/javascript/ql/src/Security/CWE-829/InsecureDownload.ql +++ b/javascript/ql/src/Security/CWE-829/InsecureDownload.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.InsecureDownload::InsecureDownload +import semmle.javascript.security.dataflow.InsecureDownloadQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql b/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql index bbbd4da1e9a..028835343c1 100644 --- a/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql +++ b/javascript/ql/src/Security/CWE-834/LoopBoundInjection.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.LoopBoundInjection::LoopBoundInjection +import semmle.javascript.security.dataflow.LoopBoundInjectionQuery import DataFlow::PathGraph from Configuration dataflow, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql index 8dbef4a8cce..795ad48409c 100644 --- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql +++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTampering::TypeConfusionThroughParameterTampering +import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTamperingQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql index 3bed7d8c190..9a8ac7b4b73 100644 --- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql +++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.HttpToFileAccess::HttpToFileAccess +import semmle.javascript.security.dataflow.HttpToFileAccessQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql index cdcc474ef92..b68a75b5b3b 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql @@ -17,7 +17,7 @@ */ import javascript -import semmle.javascript.security.dataflow.PrototypePollutingAssignment::PrototypePollutingAssignment +import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql index 53b6378fad8..f74699dcfed 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql @@ -17,7 +17,7 @@ */ import javascript -import semmle.javascript.security.dataflow.PrototypePollution::PrototypePollution +import semmle.javascript.security.dataflow.PrototypePollutionQuery import DataFlow::PathGraph import semmle.javascript.dependencies.Dependencies diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql index 61c341bba02..a40689f41df 100644 --- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql +++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.InsufficientPasswordHash::InsufficientPasswordHash +import semmle.javascript.security.dataflow.InsufficientPasswordHashQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql index 9697904ce0e..76e73d3084b 100644 --- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql +++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql @@ -11,7 +11,7 @@ */ import javascript -import semmle.javascript.security.dataflow.RequestForgery::RequestForgery +import semmle.javascript.security.dataflow.RequestForgeryQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll b/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll index 59410788889..43a56b14dbc 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll @@ -1,36 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * sensitive information in broken or weak cryptographic algorithms. - * - * Note, for performance reasons: only import this file if - * `BrokenCryptoAlgorithm::Configuration` is needed, otherwise - * `BrokenCryptoAlgorithmCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `BrokenCryptoAlgorithmQuery` instead. */ import javascript +private import BrokenCryptoAlgorithmQuery as BrokenCryptoAlgorithmQuery // ignore-query-import -module BrokenCryptoAlgorithm { - import BrokenCryptoAlgorithmCustomizations::BrokenCryptoAlgorithm - - /** - * A taint tracking configuration for sensitive information in broken or weak cryptographic algorithms. - * - * This configuration identifies flows from `Source`s, which are sources of - * sensitive data, to `Sink`s, which is an abstract class representing all - * the places sensitive data may used in broken or weak cryptographic algorithms. Additional sources or sinks can be - * added either by extending the relevant class, or by subclassing this configuration itself, - * and amending the sources and sinks. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "BrokenCryptoAlgorithm" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `BrokenCryptoAlgorithmQuery` instead. */ +deprecated module BrokenCryptoAlgorithm = BrokenCryptoAlgorithmQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll new file mode 100644 index 00000000000..d0e4d56f630 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll @@ -0,0 +1,33 @@ +/** + * Provides a taint tracking configuration for reasoning about + * sensitive information in broken or weak cryptographic algorithms. + * + * Note, for performance reasons: only import this file if + * `BrokenCryptoAlgorithm::Configuration` is needed, otherwise + * `BrokenCryptoAlgorithmCustomizations` should be imported instead. + */ + +import javascript +import BrokenCryptoAlgorithmCustomizations::BrokenCryptoAlgorithm + +/** + * A taint tracking configuration for sensitive information in broken or weak cryptographic algorithms. + * + * This configuration identifies flows from `Source`s, which are sources of + * sensitive data, to `Sink`s, which is an abstract class representing all + * the places sensitive data may used in broken or weak cryptographic algorithms. Additional sources or sinks can be + * added either by extending the relevant class, or by subclassing this configuration itself, + * and amending the sources and sinks. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "BrokenCryptoAlgorithm" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll index 5651428b7d4..f4853263d63 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll @@ -1,45 +1,7 @@ -/** - * Provides a dataflow tracking configuration for reasoning about - * storage of sensitive information in build artifact. - * - * Note, for performance reasons: only import this file if - * `CleartextLogging::Configuration` is needed, otherwise - * `CleartextLoggingCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `BuildArtifactLeakQuery` instead. */ import javascript +private import BuildArtifactLeakQuery as BuildArtifactLeakQuery // ignore-query-import -/** - * Classes and predicates for storage of sensitive information in build artifact query. - */ -module BuildArtifactLeak { - import BuildArtifactLeakCustomizations::BuildArtifactLeak - import CleartextLoggingCustomizations::CleartextLogging as CleartextLogging - - /** - * A taint tracking configuration for storage of sensitive information in build artifact. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "BuildArtifactLeak" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { - source.(CleartextLogging::Source).getLabel() = lbl - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { - sink.(Sink).getLabel() = lbl - } - - override predicate isSanitizer(DataFlow::Node node) { - node instanceof CleartextLogging::Barrier - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - CleartextLogging::isSanitizerEdge(pred, succ) - } - - override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { - CleartextLogging::isAdditionalTaintStep(src, trg) - } - } -} +/** DEPRECATED. Import `BuildArtifactLeakQuery` instead. */ +deprecated module BuildArtifactLeak = BuildArtifactLeakQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll new file mode 100644 index 00000000000..8af94f2f12c --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll @@ -0,0 +1,37 @@ +/** + * Provides a dataflow tracking configuration for reasoning about + * storage of sensitive information in build artifact. + * + * Note, for performance reasons: only import this file if + * `CleartextLogging::Configuration` is needed, otherwise + * `CleartextLoggingCustomizations` should be imported instead. + */ + +import javascript +import BuildArtifactLeakCustomizations::BuildArtifactLeak +import CleartextLoggingCustomizations::CleartextLogging as CleartextLogging + +/** + * A taint tracking configuration for storage of sensitive information in build artifact. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "BuildArtifactLeak" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { + source.(CleartextLogging::Source).getLabel() = lbl + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { + sink.(Sink).getLabel() = lbl + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof CleartextLogging::Barrier } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + CleartextLogging::isSanitizerEdge(pred, succ) + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { + CleartextLogging::isAdditionalTaintStep(src, trg) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll index 130b7120a60..40f18772fb3 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll @@ -1,45 +1,7 @@ -/** - * Provides a dataflow tracking configuration for reasoning about - * clear-text logging of sensitive information. - * - * Note, for performance reasons: only import this file if - * `CleartextLogging::Configuration` is needed, otherwise - * `CleartextLoggingCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `CleartextLoggingQuery` instead. */ import javascript +private import CleartextLoggingQuery as CleartextLoggingQuery // ignore-query-import -module CleartextLogging { - import CleartextLoggingCustomizations::CleartextLogging - - /** - * A taint tracking configuration for clear-text logging of sensitive information. - * - * This configuration identifies flows from `Source`s, which are sources of - * sensitive data, to `Sink`s, which is an abstract class representing all - * the places sensitive data may be stored in clear-text. Additional sources or sinks can be - * added either by extending the relevant class, or by subclassing this configuration itself, - * and amending the sources and sinks. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "CleartextLogging" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { - source.(Source).getLabel() = lbl - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { - sink.(Sink).getLabel() = lbl - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - CleartextLogging::isSanitizerEdge(pred, succ) - } - - override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { - CleartextLogging::isAdditionalTaintStep(src, trg) - } - } -} +/** DEPRECATED. Import `CleartextLoggingQuery` instead. */ +deprecated module CleartextLogging = CleartextLoggingQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll new file mode 100644 index 00000000000..e651f21200c --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll @@ -0,0 +1,42 @@ +/** + * Provides a dataflow tracking configuration for reasoning about + * clear-text logging of sensitive information. + * + * Note, for performance reasons: only import this file if + * `CleartextLogging::Configuration` is needed, otherwise + * `CleartextLoggingCustomizations` should be imported instead. + */ + +import javascript +import CleartextLoggingCustomizations::CleartextLogging + +/** + * A taint tracking configuration for clear-text logging of sensitive information. + * + * This configuration identifies flows from `Source`s, which are sources of + * sensitive data, to `Sink`s, which is an abstract class representing all + * the places sensitive data may be stored in clear-text. Additional sources or sinks can be + * added either by extending the relevant class, or by subclassing this configuration itself, + * and amending the sources and sinks. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "CleartextLogging" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { + source.(Source).getLabel() = lbl + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { + sink.(Sink).getLabel() = lbl + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + CleartextLogging::isSanitizerEdge(pred, succ) + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { + CleartextLogging::isAdditionalTaintStep(src, trg) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll index f8b07bba971..ac6bc090d66 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll @@ -1,33 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * cleartext storage of sensitive information. - * - * Note, for performance reasons: only import this file if - * `CleartextStorage::Configuration` is needed, otherwise - * `CleartextStorageCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `CleartextStorageQuery` instead. */ import javascript +private import CleartextStorageQuery as CleartextStorageQuery // ignore-query-import -module CleartextStorage { - import CleartextStorageCustomizations::CleartextStorage - - /** - * A taint tracking configuration for cleartext storage of sensitive information. - * - * This configuration identifies flows from `Source`s, which are sources of - * sensitive data, to `Sink`s, which is an abstract class representing all - * the places sensitive data may be stored in cleartext. Additional sources or sinks can be - * added either by extending the relevant class, or by subclassing this configuration itself, - * and amending the sources and sinks. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ClearTextStorage" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } -} +/** DEPRECATED. Import `CleartextStorageQuery` instead. */ +deprecated module CleartextStorage = CleartextStorageQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll new file mode 100644 index 00000000000..cb97badf0ec --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll @@ -0,0 +1,30 @@ +/** + * Provides a taint tracking configuration for reasoning about + * cleartext storage of sensitive information. + * + * Note, for performance reasons: only import this file if + * `CleartextStorage::Configuration` is needed, otherwise + * `CleartextStorageCustomizations` should be imported instead. + */ + +import javascript +import CleartextStorageCustomizations::CleartextStorage + +/** + * A taint tracking configuration for cleartext storage of sensitive information. + * + * This configuration identifies flows from `Source`s, which are sources of + * sensitive data, to `Sink`s, which is an abstract class representing all + * the places sensitive data may be stored in cleartext. Additional sources or sinks can be + * added either by extending the relevant class, or by subclassing this configuration itself, + * and amending the sources and sinks. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ClearTextStorage" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll index d29e48e3efa..bdf4b5c1274 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll @@ -1,71 +1,9 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * unvalidated URL redirection problems on the client side. - * - * Note, for performance reasons: only import this file if - * `ClientSideUrlRedirect::Configuration` is needed, otherwise - * `ClientSideUrlRedirectCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ClientSideUrlRedirectQuery` instead. */ import javascript import semmle.javascript.security.dataflow.RemoteFlowSources import UrlConcatenation +private import ClientSideUrlRedirectQuery as ClientSideUrlRedirectQuery // ignore-query-import -module ClientSideUrlRedirect { - import ClientSideUrlRedirectCustomizations::ClientSideUrlRedirect - - // Materialize flow labels - private class ConcreteDocumentUrl extends DocumentUrl { - ConcreteDocumentUrl() { this = this } - } - - /** - * A taint-tracking configuration for reasoning about unvalidated URL redirections. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ClientSideUrlRedirect" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { - source.(Source).getAFlowLabel() = lbl - } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { - hostnameSanitizingPrefixEdge(source, sink) - } - - override predicate isAdditionalFlowStep( - DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel f, DataFlow::FlowLabel g - ) { - untrustedUrlSubstring(pred, succ) and - f instanceof DocumentUrl and - g.isTaint() - or - // preserve document.url label in step from `location` to `location.href` - f instanceof DocumentUrl and - g instanceof DocumentUrl and - succ.(DataFlow::PropRead).accesses(pred, "href") - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof HostnameSanitizerGuard - } - } - - /** - * Improper use of openExternal can be leveraged to compromise the user's host. - * When openExternal is used with untrusted content, it can be leveraged to execute arbitrary commands. - */ - class ElectronShellOpenExternalSink extends Sink { - ElectronShellOpenExternalSink() { - this = - DataFlow::moduleMember("electron", "shell").getAMemberCall("openExternal").getArgument(0) - } - } -} +/** DEPRECATED. Import `ClientSideUrlRedirectQuery` instead. */ +deprecated module ClientSideUrlRedirect = ClientSideUrlRedirectQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll new file mode 100644 index 00000000000..3e8825d5dd5 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll @@ -0,0 +1,67 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * unvalidated URL redirection problems on the client side. + * + * Note, for performance reasons: only import this file if + * `ClientSideUrlRedirect::Configuration` is needed, otherwise + * `ClientSideUrlRedirectCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.RemoteFlowSources +import UrlConcatenation +import ClientSideUrlRedirectCustomizations::ClientSideUrlRedirect + +// Materialize flow labels +private class ConcreteDocumentUrl extends DocumentUrl { + ConcreteDocumentUrl() { this = this } +} + +/** + * A taint-tracking configuration for reasoning about unvalidated URL redirections. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ClientSideUrlRedirect" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { + source.(Source).getAFlowLabel() = lbl + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { + hostnameSanitizingPrefixEdge(source, sink) + } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel f, DataFlow::FlowLabel g + ) { + untrustedUrlSubstring(pred, succ) and + f instanceof DocumentUrl and + g.isTaint() + or + // preserve document.url label in step from `location` to `location.href` + f instanceof DocumentUrl and + g instanceof DocumentUrl and + succ.(DataFlow::PropRead).accesses(pred, "href") + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof HostnameSanitizerGuard + } +} + +/** + * Improper use of openExternal can be leveraged to compromise the user's host. + * When openExternal is used with untrusted content, it can be leveraged to execute arbitrary commands. + */ +class ElectronShellOpenExternalSink extends Sink { + ElectronShellOpenExternalSink() { + this = DataFlow::moduleMember("electron", "shell").getAMemberCall("openExternal").getArgument(0) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll index a2dcb306e25..6c03cef6cd3 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll @@ -1,35 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about code - * injection vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `CodeInjection::Configuration` is needed, otherwise - * `CodeInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `CodeInjectionQuery` instead. */ import javascript +private import CodeInjectionQuery as CodeInjectionQuery // ignore-query-import -module CodeInjection { - import CodeInjectionCustomizations::CodeInjection - - /** - * A taint-tracking configuration for reasoning about code injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "CodeInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { - // HTML sanitizers are insufficient protection against code injection - src = trg.(HtmlSanitizerCall).getInput() - } - } -} +/** DEPRECATED. Import `CodeInjectionQuery` instead. */ +deprecated module CodeInjection = CodeInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll new file mode 100644 index 00000000000..ea57dd73588 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll @@ -0,0 +1,32 @@ +/** + * Provides a taint-tracking configuration for reasoning about code + * injection vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `CodeInjection::Configuration` is needed, otherwise + * `CodeInjectionCustomizations` should be imported instead. + */ + +import javascript +import CodeInjectionCustomizations::CodeInjection + +/** + * A taint-tracking configuration for reasoning about code injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "CodeInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { + // HTML sanitizers are insufficient protection against code injection + src = trg.(HtmlSanitizerCall).getInput() + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll index ff40919e25e..b424c3695e1 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll @@ -1,38 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * command-injection vulnerabilities (CWE-078). - * - * Note, for performance reasons: only import this file if - * `CommandInjection::Configuration` is needed, otherwise - * `CommandInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `CommandInjectionQuery` instead. */ import javascript +private import CommandInjectionQuery as CommandInjectionQuery // ignore-query-import -module CommandInjection { - import CommandInjectionCustomizations::CommandInjection - import IndirectCommandArgument - - /** - * A taint-tracking configuration for reasoning about command-injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "CommandInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - /** - * Holds if `sink` is a data flow sink for command-injection vulnerabilities, and - * the alert should be placed at the node `highlight`. - */ - predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { - sink instanceof Sink and highlight = sink - or - isIndirectCommandArgument(sink, highlight) - } - - override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } -} +/** DEPRECATED. Import `CommandInjectionQuery` instead. */ +deprecated module CommandInjection = CommandInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll new file mode 100644 index 00000000000..64541f77e37 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll @@ -0,0 +1,35 @@ +/** + * Provides a taint tracking configuration for reasoning about + * command-injection vulnerabilities (CWE-078). + * + * Note, for performance reasons: only import this file if + * `CommandInjection::Configuration` is needed, otherwise + * `CommandInjectionCustomizations` should be imported instead. + */ + +import javascript +import CommandInjectionCustomizations::CommandInjection +import IndirectCommandArgument + +/** + * A taint-tracking configuration for reasoning about command-injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "CommandInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + /** + * Holds if `sink` is a data flow sink for command-injection vulnerabilities, and + * the alert should be placed at the node `highlight`. + */ + predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { + sink instanceof Sink and highlight = sink + or + isIndirectCommandArgument(sink, highlight) + } + + override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll index fb760c9092f..54f1e9418fc 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll @@ -1,35 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about bypass of sensitive action guards. - * - * Note, for performance reasons: only import this file if - * `ConditionalBypass::Configuration` is needed, otherwise - * `ConditionalBypassCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ConditionalBypassQuery` instead. */ import javascript -private import semmle.javascript.security.SensitiveActions +private import ConditionalBypassQuery as ConditionalBypassQuery // ignore-query-import -module ConditionalBypass { - import ConditionalBypassCustomizations::ConditionalBypass - - /** - * A taint tracking configuration for bypass of sensitive action guards. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ConditionalBypass" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) { - // comparing a tainted expression against a constant gives a tainted result - dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c)) - } - } -} +/** DEPRECATED. Import `ConditionalBypassQuery` instead. */ +deprecated module ConditionalBypass = ConditionalBypassQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll new file mode 100644 index 00000000000..9a5e9c45b77 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll @@ -0,0 +1,32 @@ +/** + * Provides a taint tracking configuration for reasoning about bypass of sensitive action guards. + * + * Note, for performance reasons: only import this file if + * `ConditionalBypass::Configuration` is needed, otherwise + * `ConditionalBypassCustomizations` should be imported instead. + */ + +import javascript +private import semmle.javascript.security.SensitiveActions +import ConditionalBypassCustomizations::ConditionalBypass + +/** + * A taint tracking configuration for bypass of sensitive action guards. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ConditionalBypass" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) { + // comparing a tainted expression against a constant gives a tainted result + dst.asExpr().(Comparison).hasOperands(src.asExpr(), any(ConstantExpr c)) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll index 5a0d80616d3..06a6378e8ef 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll @@ -1,35 +1,7 @@ -/** - * Provides a dataflow taint tracking configuration for reasoning - * about CORS misconfiguration for credentials transfer. - * - * Note, for performance reasons: only import this file if - * `CorsMisconfigurationForCredentials::Configuration` is needed, - * otherwise `CorsMisconfigurationForCredentialsCustomizations` should - * be imported instead. - */ +/** DEPRECATED. Import `CorsMisconfigurationForCredentialsQuery` instead. */ import javascript +private import CorsMisconfigurationForCredentialsQuery as CorsMisconfigurationForCredentialsQuery // ignore-query-import -module CorsMisconfigurationForCredentials { - import CorsMisconfigurationForCredentialsCustomizations::CorsMisconfigurationForCredentials - - /** - * A data flow configuration for CORS misconfiguration for credentials transfer. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "CorsMisconfigurationForCredentials" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer - } - } -} +/** DEPRECATED. Import `CorsMisconfigurationForCredentialsQuery` instead. */ +deprecated module CorsMisconfigurationForCredentials = CorsMisconfigurationForCredentialsQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll new file mode 100644 index 00000000000..57cabe0ea79 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll @@ -0,0 +1,32 @@ +/** + * Provides a dataflow taint tracking configuration for reasoning + * about CORS misconfiguration for credentials transfer. + * + * Note, for performance reasons: only import this file if + * `CorsMisconfigurationForCredentials::Configuration` is needed, + * otherwise `CorsMisconfigurationForCredentialsCustomizations` should + * be imported instead. + */ + +import javascript +import CorsMisconfigurationForCredentialsCustomizations::CorsMisconfigurationForCredentials + +/** + * A data flow configuration for CORS misconfiguration for credentials transfer. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "CorsMisconfigurationForCredentials" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll index 31bccc11162..82d9f4156a5 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll @@ -1,41 +1,8 @@ -/** - * Provides a taint tracking configuration for reasoning about DoS attacks - * due to inefficient handling of user-controlled objects. - */ +/** DEPRECATED. Import `DeepObjectResourceExhaustionQuery` instead. */ import javascript import semmle.javascript.security.TaintedObject +private import DeepObjectResourceExhaustionQuery as DeepObjectResourceExhaustionQuery // ignore-query-import -/** - * Provides a taint tracking configuration for reasoning about DoS attacks - * due to inefficient handling of user-controlled objects. - */ -module DeepObjectResourceExhaustion { - import DeepObjectResourceExhaustionCustomizations::DeepObjectResourceExhaustion - - /** - * A taint tracking configuration for reasoning about DoS attacks due to inefficient handling - * of user-controlled objects. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "DeepObjectResourceExhaustion" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getAFlowLabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink instanceof Sink and label = TaintedObject::label() - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TaintedObject::SanitizerGuard - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedObject::step(src, trg, inlbl, outlbl) - } - } -} +/** DEPRECATED. Import `DeepObjectResourceExhaustionQuery` instead. */ +deprecated module DeepObjectResourceExhaustion = DeepObjectResourceExhaustionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll new file mode 100644 index 00000000000..4f693a193dc --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll @@ -0,0 +1,34 @@ +/** + * Provides a taint tracking configuration for reasoning about DoS attacks + * due to inefficient handling of user-controlled objects. + */ + +import javascript +import semmle.javascript.security.TaintedObject +import DeepObjectResourceExhaustionCustomizations::DeepObjectResourceExhaustion + +/** + * A taint tracking configuration for reasoning about DoS attacks due to inefficient handling + * of user-controlled objects. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "DeepObjectResourceExhaustion" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof Sink and label = TaintedObject::label() + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, trg, inlbl, outlbl) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll index 6693a0329f5..9e786db7cfa 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll @@ -1,54 +1,8 @@ -/** - * Provides classes for reasoning about comparisons that relies on - * different kinds of HTTP request data. - * - * Note, for performance reasons: only import this file if - * `DifferentKindsComparisonBypass::Configuration` is needed, - * otherwise `DifferentKindsComparisonBypassCustomizations` should be - * imported instead. - */ +/** DEPRECATED. Import `DifferentKindsComparisonBypassQuery` instead. */ import javascript import semmle.javascript.security.dataflow.RemoteFlowSources +private import DifferentKindsComparisonBypassQuery as DifferentKindsComparisonBypassQuery // ignore-query-import -module DifferentKindsComparisonBypass { - import DifferentKindsComparisonBypassCustomizations::DifferentKindsComparisonBypass - - /** - * A taint tracking configuration for comparisons that relies on different kinds of HTTP request data. - */ - private class Configuration extends TaintTracking::Configuration { - Configuration() { this = "DifferentKindsComparisonBypass" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } - - /** - * A comparison that relies on different kinds of HTTP request data. - */ - class DifferentKindsComparison extends Comparison { - Source lSource; - Source rSource; - - DifferentKindsComparison() { - exists(Configuration cfg | - cfg.hasFlow(lSource, DataFlow::valueNode(getLeftOperand())) and - cfg.hasFlow(rSource, DataFlow::valueNode(getRightOperand())) and - lSource.isSuspiciousToCompareWith(rSource) - ) - } - - /** Gets the left operand source of this comparison. */ - Source getLSource() { result = lSource } - - /** Gets the right operand source of this comparison. */ - Source getRSource() { result = rSource } - } -} +/** DEPRECATED. Import `DifferentKindsComparisonBypassQuery` instead. */ +deprecated module DifferentKindsComparisonBypass = DifferentKindsComparisonBypassQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll new file mode 100644 index 00000000000..d3639b98a01 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll @@ -0,0 +1,51 @@ +/** + * Provides classes for reasoning about comparisons that relies on + * different kinds of HTTP request data. + * + * Note, for performance reasons: only import this file if + * `DifferentKindsComparisonBypass::Configuration` is needed, + * otherwise `DifferentKindsComparisonBypassCustomizations` should be + * imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.RemoteFlowSources +import DifferentKindsComparisonBypassCustomizations::DifferentKindsComparisonBypass + +/** + * A taint tracking configuration for comparisons that relies on different kinds of HTTP request data. + */ +private class Configuration extends TaintTracking::Configuration { + Configuration() { this = "DifferentKindsComparisonBypass" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} + +/** + * A comparison that relies on different kinds of HTTP request data. + */ +class DifferentKindsComparison extends Comparison { + Source lSource; + Source rSource; + + DifferentKindsComparison() { + exists(Configuration cfg | + cfg.hasFlow(lSource, DataFlow::valueNode(getLeftOperand())) and + cfg.hasFlow(rSource, DataFlow::valueNode(getRightOperand())) and + lSource.isSuspiciousToCompareWith(rSource) + ) + } + + /** Gets the left operand source of this comparison. */ + Source getLSource() { result = lSource } + + /** Gets the right operand source of this comparison. */ + Source getRSource() { result = rSource } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll index cf8bbe07147..9a687eb06a0 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll @@ -1,96 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about DOM-based - * cross-site scripting vulnerabilities. - */ +/** DEPRECATED. Import `DomBasedXssQuery` instead. */ import javascript -private import semmle.javascript.security.TaintedUrlSuffix +private import DomBasedXssQuery as DomBasedXssQuery // ignore-query-import -module DomBasedXss { - import DomBasedXssCustomizations::DomBasedXss - - /** - * DEPRECATED. Use `HtmlInjectionConfiguration` or `JQueryHtmlOrSelectorInjectionConfiguration`. - */ - deprecated class Configuration = HtmlInjectionConfiguration; - - /** - * DEPRECATED. Use `Vue::VHtmlSourceWrite` instead. - */ - deprecated class VHtmlSourceWrite = Vue::VHtmlSourceWrite; - - /** - * A taint-tracking configuration for reasoning about XSS. - */ - class HtmlInjectionConfiguration extends TaintTracking::Configuration { - HtmlInjectionConfiguration() { this = "HtmlInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { - sink instanceof Sink and - not sink instanceof JQueryHtmlOrSelectorSink // Handled by JQueryHtmlOrSelectorInjectionConfiguration below - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) - or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof SanitizerGuard - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - DomBasedXss::isOptionallySanitizedEdge(pred, succ) - } - } - - /** - * A taint-tracking configuration for reasoning about injection into the jQuery `$` function - * or similar, where the interpretation of the input string depends on its first character. - * - * Values are only considered tainted if they can start with the `<` character. - */ - class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking::Configuration { - JQueryHtmlOrSelectorInjectionConfiguration() { this = "JQueryHtmlOrSelectorInjection" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - // Reuse any source not derived from location - source instanceof Source and - not source = [DOM::locationRef(), DOM::locationRef().getAPropertyRead()] and - label.isTaint() - or - source = [DOM::locationSource(), DOM::locationRef().getAPropertyRead(["hash", "search"])] and - label = TaintedUrlSuffix::label() - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink instanceof JQueryHtmlOrSelectorSink and label.isTaint() - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) - or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof SanitizerGuard - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedUrlSuffix::step(src, trg, inlbl, outlbl) - or - exists(DataFlow::Node operator | - StringConcatenation::taintStep(src, trg, operator, _) and - StringConcatenation::getOperand(operator, 0).getStringValue() = "<" + any(string s) and - inlbl = TaintedUrlSuffix::label() and - outlbl.isTaint() - ) - } - } -} +/** DEPRECATED. Import `DomBasedXssQuery` instead. */ +deprecated module DomBasedXss = DomBasedXssQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll new file mode 100644 index 00000000000..a42d974c34b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll @@ -0,0 +1,93 @@ +/** + * Provides a taint-tracking configuration for reasoning about DOM-based + * cross-site scripting vulnerabilities. + */ + +import javascript +private import semmle.javascript.security.TaintedUrlSuffix +import DomBasedXssCustomizations::DomBasedXss + +/** + * DEPRECATED. Use `HtmlInjectionConfiguration` or `JQueryHtmlOrSelectorInjectionConfiguration`. + */ +deprecated class Configuration = HtmlInjectionConfiguration; + +/** + * DEPRECATED. Use `Vue::VHtmlSourceWrite` instead. + */ +deprecated class VHtmlSourceWrite = Vue::VHtmlSourceWrite; + +/** + * A taint-tracking configuration for reasoning about XSS. + */ +class HtmlInjectionConfiguration extends TaintTracking::Configuration { + HtmlInjectionConfiguration() { this = "HtmlInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof Sink and + not sink instanceof JQueryHtmlOrSelectorSink // Handled by JQueryHtmlOrSelectorInjectionConfiguration below + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof SanitizerGuard + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + DomBasedXss::isOptionallySanitizedEdge(pred, succ) + } +} + +/** + * A taint-tracking configuration for reasoning about injection into the jQuery `$` function + * or similar, where the interpretation of the input string depends on its first character. + * + * Values are only considered tainted if they can start with the `<` character. + */ +class JQueryHtmlOrSelectorInjectionConfiguration extends TaintTracking::Configuration { + JQueryHtmlOrSelectorInjectionConfiguration() { this = "JQueryHtmlOrSelectorInjection" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + // Reuse any source not derived from location + source instanceof Source and + not source = [DOM::locationRef(), DOM::locationRef().getAPropertyRead()] and + label.isTaint() + or + source = [DOM::locationSource(), DOM::locationRef().getAPropertyRead(["hash", "search"])] and + label = TaintedUrlSuffix::label() + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof JQueryHtmlOrSelectorSink and label.isTaint() + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedUrlSuffix::step(src, trg, inlbl, outlbl) + or + exists(DataFlow::Node operator | + StringConcatenation::taintStep(src, trg, operator, _) and + StringConcatenation::getOperand(operator, 0).getStringValue() = "<" + any(string s) and + inlbl = TaintedUrlSuffix::label() and + outlbl.isTaint() + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll index 3340df26e72..7f133319438 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll @@ -1,162 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about cross-site - * scripting vulnerabilities where the taint-flow passes through a thrown - * exception. - */ +/** DEPRECATED. Import `ExceptionXssQuery` instead. */ import javascript +private import ExceptionXssQuery as ExceptionXssQuery // ignore-query-import -module ExceptionXss { - import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom - import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom - import Xss as Xss - import Xss::ExceptionXss - private import semmle.javascript.dataflow.InferredTypes - - /** - * Gets the name of a method that does not leak taint from its arguments if an exception is thrown by the method. - */ - private string getAnUnlikelyToThrowMethodName() { - result = "getElementById" or // document.getElementById - result = "indexOf" or // String.prototype.indexOf - result = "assign" or // Object.assign - result = "pick" or // _.pick - result = getAStandardLoggerMethodName() or // log.info etc. - result = "val" or // $.val - result = "parse" or // JSON.parse - result = "stringify" or // JSON.stringify - result = "test" or // RegExp.prototype.test - result = "setItem" or // localStorage.setItem - result = "existsSync" or - // the "fs" methods are a mix of "this is safe" and "you have bigger problems". - exists(ExternalMemberDecl decl | decl.hasQualifiedName("fs", result)) or - // Array methods are generally exception safe. - exists(ExternalMemberDecl decl | decl.hasQualifiedName("Array", result)) - } - - /** - * Holds if `node` is unlikely to cause an exception containing sensitive information to be thrown. - */ - private predicate isUnlikelyToThrowSensitiveInformation(DataFlow::Node node) { - node = - any(DataFlow::CallNode call | call.getCalleeName() = getAnUnlikelyToThrowMethodName()) - .getAnArgument() - or - node = DataFlow::globalVarRef("console").getAMemberCall(_).getAnArgument() - } - - /** - * Holds if `t` is `null` or `undefined`. - */ - private predicate isNullOrUndefined(InferredType t) { - t = TTNull() or - t = TTUndefined() - } - - /** - * Holds if `node` can possibly cause an exception containing sensitive information to be thrown. - */ - predicate canThrowSensitiveInformation(DataFlow::Node node) { - not isUnlikelyToThrowSensitiveInformation(node) and - not node instanceof Xss::Shared::Sink and // removes duplicates from js/xss. - ( - // in the case of reflective calls the below ensures that both InvokeNodes have no known callee. - forex(DataFlow::InvokeNode call | call.getAnArgument() = node | not exists(call.getACallee())) - or - node.asExpr().getEnclosingStmt() instanceof ThrowStmt - or - exists(DataFlow::PropRef prop | - node = DataFlow::valueNode(prop.getPropertyNameExpr()) and - forex(InferredType t | t = prop.getBase().analyze().getAType() | isNullOrUndefined(t)) - ) - ) - } - - // Materialize flow labels - private class ConcreteNotYetThrown extends Xss::ExceptionXss::NotYetThrown { - ConcreteNotYetThrown() { this = this } - } - - /** - * A callback that is the last argument to some call, and the callback has the form: - * `function (err, value) {if (err) {...} ... }` - */ - class Callback extends DataFlow::FunctionNode { - DataFlow::ParameterNode errorParameter; - - Callback() { - exists(DataFlow::CallNode call | call.getLastArgument().getAFunctionValue() = this) and - this.getNumParameter() = 2 and - errorParameter = this.getParameter(0) and - exists(IfStmt ifStmt | - ifStmt = this.getFunction().getBodyStmt(0) and - errorParameter.flowsToExpr(ifStmt.getCondition()) - ) - } - - /** - * Gets the parameter in the callback that contains an error. - * In the current implementation this is always the first parameter. - */ - DataFlow::Node getErrorParam() { result = errorParameter } - } - - /** - * Gets the error parameter for a callback that is supplied to the same call as `pred` is an argument to. - * For example: `outerCall(foo, , bar, (, val) => { ... })`. - */ - DataFlow::Node getCallbackErrorParam(DataFlow::Node pred) { - exists(DataFlow::CallNode call, Callback callback | - pred = call.getAnArgument() and - call.getLastArgument() = callback and - result = callback.getErrorParam() and - not pred = callback - ) - } - - /** - * Gets the data-flow node to which any exceptions thrown by - * this expression will propagate. - * This predicate adds, on top of `Expr::getExceptionTarget`, exceptions - * propagated by callbacks. - */ - private DataFlow::Node getExceptionTarget(DataFlow::Node pred) { - result = pred.asExpr().getExceptionTarget() - or - result = getCallbackErrorParam(pred) - } - - /** - * A taint-tracking configuration for reasoning about XSS with possible exceptional flow. - * Flow labels are used to ensure that we only report taint-flow that has been thrown in - * an exception. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ExceptionXss" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Xss::ExceptionXss::Source).getAFlowLabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink instanceof Xss::Shared::Sink and not label instanceof NotYetThrown - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Xss::Shared::Sanitizer } - - override predicate isAdditionalFlowStep( - DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, - DataFlow::FlowLabel outlbl - ) { - inlbl instanceof NotYetThrown and - (outlbl.isTaint() or outlbl instanceof NotYetThrown) and - canThrowSensitiveInformation(pred) and - succ = getExceptionTarget(pred) - or - // All the usual taint-flow steps apply on data-flow before it has been thrown in an exception. - this.isAdditionalFlowStep(pred, succ) and - inlbl instanceof NotYetThrown and - outlbl instanceof NotYetThrown - } - } -} +/** DEPRECATED. Import `ExceptionXssQuery` instead. */ +deprecated module ExceptionXss = ExceptionXssQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll new file mode 100644 index 00000000000..dd3e9246817 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll @@ -0,0 +1,158 @@ +/** + * Provides a taint-tracking configuration for reasoning about cross-site + * scripting vulnerabilities where the taint-flow passes through a thrown + * exception. + */ + +import javascript +import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom +import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom +import Xss as Xss +import Xss::ExceptionXss +private import semmle.javascript.dataflow.InferredTypes + +/** + * Gets the name of a method that does not leak taint from its arguments if an exception is thrown by the method. + */ +private string getAnUnlikelyToThrowMethodName() { + result = "getElementById" or // document.getElementById + result = "indexOf" or // String.prototype.indexOf + result = "assign" or // Object.assign + result = "pick" or // _.pick + result = getAStandardLoggerMethodName() or // log.info etc. + result = "val" or // $.val + result = "parse" or // JSON.parse + result = "stringify" or // JSON.stringify + result = "test" or // RegExp.prototype.test + result = "setItem" or // localStorage.setItem + result = "existsSync" or + // the "fs" methods are a mix of "this is safe" and "you have bigger problems". + exists(ExternalMemberDecl decl | decl.hasQualifiedName("fs", result)) or + // Array methods are generally exception safe. + exists(ExternalMemberDecl decl | decl.hasQualifiedName("Array", result)) +} + +/** + * Holds if `node` is unlikely to cause an exception containing sensitive information to be thrown. + */ +private predicate isUnlikelyToThrowSensitiveInformation(DataFlow::Node node) { + node = + any(DataFlow::CallNode call | call.getCalleeName() = getAnUnlikelyToThrowMethodName()) + .getAnArgument() + or + node = DataFlow::globalVarRef("console").getAMemberCall(_).getAnArgument() +} + +/** + * Holds if `t` is `null` or `undefined`. + */ +private predicate isNullOrUndefined(InferredType t) { + t = TTNull() or + t = TTUndefined() +} + +/** + * Holds if `node` can possibly cause an exception containing sensitive information to be thrown. + */ +predicate canThrowSensitiveInformation(DataFlow::Node node) { + not isUnlikelyToThrowSensitiveInformation(node) and + not node instanceof Xss::Shared::Sink and // removes duplicates from js/xss. + ( + // in the case of reflective calls the below ensures that both InvokeNodes have no known callee. + forex(DataFlow::InvokeNode call | call.getAnArgument() = node | not exists(call.getACallee())) + or + node.asExpr().getEnclosingStmt() instanceof ThrowStmt + or + exists(DataFlow::PropRef prop | + node = DataFlow::valueNode(prop.getPropertyNameExpr()) and + forex(InferredType t | t = prop.getBase().analyze().getAType() | isNullOrUndefined(t)) + ) + ) +} + +// Materialize flow labels +private class ConcreteNotYetThrown extends Xss::ExceptionXss::NotYetThrown { + ConcreteNotYetThrown() { this = this } +} + +/** + * A callback that is the last argument to some call, and the callback has the form: + * `function (err, value) {if (err) {...} ... }` + */ +class Callback extends DataFlow::FunctionNode { + DataFlow::ParameterNode errorParameter; + + Callback() { + exists(DataFlow::CallNode call | call.getLastArgument().getAFunctionValue() = this) and + this.getNumParameter() = 2 and + errorParameter = this.getParameter(0) and + exists(IfStmt ifStmt | + ifStmt = this.getFunction().getBodyStmt(0) and + errorParameter.flowsToExpr(ifStmt.getCondition()) + ) + } + + /** + * Gets the parameter in the callback that contains an error. + * In the current implementation this is always the first parameter. + */ + DataFlow::Node getErrorParam() { result = errorParameter } +} + +/** + * Gets the error parameter for a callback that is supplied to the same call as `pred` is an argument to. + * For example: `outerCall(foo, , bar, (, val) => { ... })`. + */ +DataFlow::Node getCallbackErrorParam(DataFlow::Node pred) { + exists(DataFlow::CallNode call, Callback callback | + pred = call.getAnArgument() and + call.getLastArgument() = callback and + result = callback.getErrorParam() and + not pred = callback + ) +} + +/** + * Gets the data-flow node to which any exceptions thrown by + * this expression will propagate. + * This predicate adds, on top of `Expr::getExceptionTarget`, exceptions + * propagated by callbacks. + */ +private DataFlow::Node getExceptionTarget(DataFlow::Node pred) { + result = pred.asExpr().getExceptionTarget() + or + result = getCallbackErrorParam(pred) +} + +/** + * A taint-tracking configuration for reasoning about XSS with possible exceptional flow. + * Flow labels are used to ensure that we only report taint-flow that has been thrown in + * an exception. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ExceptionXss" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Xss::ExceptionXss::Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof Xss::Shared::Sink and not label instanceof NotYetThrown + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Xss::Shared::Sanitizer } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + inlbl instanceof NotYetThrown and + (outlbl.isTaint() or outlbl instanceof NotYetThrown) and + canThrowSensitiveInformation(pred) and + succ = getExceptionTarget(pred) + or + // All the usual taint-flow steps apply on data-flow before it has been thrown in an exception. + this.isAdditionalFlowStep(pred, succ) and + inlbl instanceof NotYetThrown and + outlbl instanceof NotYetThrown + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll index 939d111f374..801accf4f11 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll @@ -1,106 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about untrusted - * data flowing to an external API call. - * - * Note, for performance reasons: only import this file if - * `ExternalAPIUsedWithUntrustedData::Configuration` is needed, otherwise - * `ExternalAPIUsedWithUntrustedDataCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ExternalAPIUsedWithUntrustedDataQuery` instead. */ import javascript +private import ExternalAPIUsedWithUntrustedDataQuery as ExternalAPIUsedWithUntrustedDataQuery // ignore-query-import -/** - * Provides a taint tracking configuration for reasoning about untrusted - * data flowing to an external API call. - */ -module ExternalAPIUsedWithUntrustedData { - import ExternalAPIUsedWithUntrustedDataCustomizations::ExternalAPIUsedWithUntrustedData - - /** Flow label for objects from which a tainted value is reachable. */ - private class ObjectWrapperFlowLabel extends DataFlow::FlowLabel { - ObjectWrapperFlowLabel() { this = "object-wrapper" } - } - - /** - * A taint tracking configuration for untrusted data flowing to an external API. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ExternalAPIUsedWithUntrustedData" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { - sink instanceof Sink and - (lbl.isTaint() or lbl instanceof ObjectWrapperFlowLabel) - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isAdditionalFlowStep( - DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predLbl, - DataFlow::FlowLabel succLbl - ) { - // Step into an object and switch to the 'object-wrapper' label. - exists(DataFlow::PropWrite write | - pred = write.getRhs() and - succ = write.getBase().getALocalSource() and - (predLbl.isTaint() or predLbl instanceof ObjectWrapperFlowLabel) and - succLbl instanceof ObjectWrapperFlowLabel - ) - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - // Block flow from the location to its properties, as the relevant properties (hash and search) are taint sources of their own. - // The location source is only used for propagating through API calls like `new URL(location)` and into external APIs where - // the whole location object escapes. - exists(DataFlow::PropRead read | - read = DOM::locationRef().getAPropertyRead() and - pred = read.getBase() and - succ = read - ) - } - } - - /** A node representing data being passed to an external API. */ - class ExternalAPIDataNode extends DataFlow::Node { - ExternalAPIDataNode() { this instanceof Sink } - } - - /** A node representing untrusted data being passed to an external API. */ - class UntrustedExternalAPIDataNode extends ExternalAPIDataNode { - UntrustedExternalAPIDataNode() { any(Configuration c).hasFlow(_, this) } - - /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { any(Configuration c).hasFlow(result, this) } - } - - /** - * Name of an external API sink, boxed in a newtype for consistency with other languages. - */ - private newtype TExternalApi = - MkExternalApiNode(string name) { - exists(Sink sink | - any(Configuration c).hasFlow(_, sink) and - name = sink.getApiName() - ) - } - - /** 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 = MkExternalApiNode(result.(Sink).getApiName()) - } - - /** 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() { this = MkExternalApiNode(result) } - } -} +/** DEPRECATED. Import `ExternalAPIUsedWithUntrustedDataQuery` instead. */ +deprecated module ExternalAPIUsedWithUntrustedData = ExternalAPIUsedWithUntrustedDataQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll new file mode 100644 index 00000000000..d9675c05997 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll @@ -0,0 +1,99 @@ +/** + * Provides a taint tracking configuration for reasoning about untrusted + * data flowing to an external API call. + * + * Note, for performance reasons: only import this file if + * `ExternalAPIUsedWithUntrustedData::Configuration` is needed, otherwise + * `ExternalAPIUsedWithUntrustedDataCustomizations` should be imported instead. + */ + +import javascript +import ExternalAPIUsedWithUntrustedDataCustomizations::ExternalAPIUsedWithUntrustedData + +/** Flow label for objects from which a tainted value is reachable. */ +private class ObjectWrapperFlowLabel extends DataFlow::FlowLabel { + ObjectWrapperFlowLabel() { this = "object-wrapper" } +} + +/** + * A taint tracking configuration for untrusted data flowing to an external API. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ExternalAPIUsedWithUntrustedData" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { + sink instanceof Sink and + (lbl.isTaint() or lbl instanceof ObjectWrapperFlowLabel) + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predLbl, + DataFlow::FlowLabel succLbl + ) { + // Step into an object and switch to the 'object-wrapper' label. + exists(DataFlow::PropWrite write | + pred = write.getRhs() and + succ = write.getBase().getALocalSource() and + (predLbl.isTaint() or predLbl instanceof ObjectWrapperFlowLabel) and + succLbl instanceof ObjectWrapperFlowLabel + ) + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + // Block flow from the location to its properties, as the relevant properties (hash and search) are taint sources of their own. + // The location source is only used for propagating through API calls like `new URL(location)` and into external APIs where + // the whole location object escapes. + exists(DataFlow::PropRead read | + read = DOM::locationRef().getAPropertyRead() and + pred = read.getBase() and + succ = read + ) + } +} + +/** A node representing data being passed to an external API. */ +class ExternalAPIDataNode extends DataFlow::Node { + ExternalAPIDataNode() { this instanceof Sink } +} + +/** A node representing untrusted data being passed to an external API. */ +class UntrustedExternalAPIDataNode extends ExternalAPIDataNode { + UntrustedExternalAPIDataNode() { any(Configuration c).hasFlow(_, this) } + + /** Gets a source of untrusted data which is passed to this external API data node. */ + DataFlow::Node getAnUntrustedSource() { any(Configuration c).hasFlow(result, this) } +} + +/** + * Name of an external API sink, boxed in a newtype for consistency with other languages. + */ +private newtype TExternalApi = + MkExternalApiNode(string name) { + exists(Sink sink | + any(Configuration c).hasFlow(_, sink) and + name = sink.getApiName() + ) + } + +/** 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 = MkExternalApiNode(result.(Sink).getApiName()) + } + + /** 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() { this = MkExternalApiNode(result) } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll b/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll index 186053b677d..7b6e88d0669 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll @@ -1,38 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about file - * data in outbound network requests. - * - * Note, for performance reasons: only import this file if - * `FileAccessToHttp::Configuration` is needed, otherwise - * `FileAccessToHttpCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `FileAccessToHttpQuery` instead. */ import javascript +private import FileAccessToHttpQuery as FileAccessToHttpQuery // ignore-query-import -module FileAccessToHttp { - import FileAccessToHttpCustomizations::FileAccessToHttp - - /** - * A taint tracking configuration for file data in outbound network requests. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "FileAccessToHttp" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - // taint entire object on property write - exists(DataFlow::PropWrite pwr | - succ = pwr.getBase() and - pred = pwr.getRhs() - ) - } - } -} +/** DEPRECATED. Import `FileAccessToHttpQuery` instead. */ +deprecated module FileAccessToHttp = FileAccessToHttpQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll new file mode 100644 index 00000000000..9ce03476755 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll @@ -0,0 +1,35 @@ +/** + * Provides a taint tracking configuration for reasoning about file + * data in outbound network requests. + * + * Note, for performance reasons: only import this file if + * `FileAccessToHttp::Configuration` is needed, otherwise + * `FileAccessToHttpCustomizations` should be imported instead. + */ + +import javascript +import FileAccessToHttpCustomizations::FileAccessToHttp + +/** + * A taint tracking configuration for file data in outbound network requests. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "FileAccessToHttp" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + // taint entire object on property write + exists(DataFlow::PropWrite pwr | + succ = pwr.getBase() and + pred = pwr.getRhs() + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll index db65b6b2acc..9fabc93d9ac 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll @@ -1,37 +1,7 @@ -/** - * Provides a data flow configuration for reasoning about hardcoded - * credentials. - * Note, for performance reasons: only import this file if - * `HardcodedCredentials::Configuration` is needed, otherwise - * `HardcodedCredentialsCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `HardcodedCredentialsQuery` instead. */ import javascript +private import HardcodedCredentialsQuery as HardcodedCredentialsQuery // ignore-query-import -module HardcodedCredentials { - import HardcodedCredentialsCustomizations::HardcodedCredentials - - /** - * A data flow tracking configuration for hardcoded credentials. - */ - class Configuration extends DataFlow::Configuration { - Configuration() { this = "HardcodedCredentials" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) { - exists(Base64::Encode encode | src = encode.getInput() and trg = encode.getOutput()) - or - trg.(StringOps::ConcatenationRoot).getALeaf() = src and - not exists(src.(StringOps::ConcatenationLeaf).getStringValue()) // to avoid e.g. the ":" in `user + ":" + pass` being flagged as a constant credential. - or - exists(DataFlow::MethodCallNode bufferFrom | - bufferFrom = DataFlow::globalVarRef("Buffer").getAMethodCall("from") and - trg = bufferFrom and - src = bufferFrom.getArgument(0) - ) - } - } -} +/** DEPRECATED. Import `HardcodedCredentialsQuery` instead. */ +deprecated module HardcodedCredentials = HardcodedCredentialsQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll new file mode 100644 index 00000000000..2b84c54e5e1 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll @@ -0,0 +1,34 @@ +/** + * Provides a data flow configuration for reasoning about hardcoded + * credentials. + * Note, for performance reasons: only import this file if + * `HardcodedCredentials::Configuration` is needed, otherwise + * `HardcodedCredentialsCustomizations` should be imported instead. + */ + +import javascript +import HardcodedCredentialsCustomizations::HardcodedCredentials + +/** + * A data flow tracking configuration for hardcoded credentials. + */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "HardcodedCredentials" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) { + exists(Base64::Encode encode | src = encode.getInput() and trg = encode.getOutput()) + or + trg.(StringOps::ConcatenationRoot).getALeaf() = src and + not exists(src.(StringOps::ConcatenationLeaf).getStringValue()) // to avoid e.g. the ":" in `user + ":" + pass` being flagged as a constant credential. + or + exists(DataFlow::MethodCallNode bufferFrom | + bufferFrom = DataFlow::globalVarRef("Buffer").getAMethodCall("from") and + trg = bufferFrom and + src = bufferFrom.getArgument(0) + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll index bca5acd1dd9..e1ca461183a 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll @@ -1,33 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about hard-coded data - * being interpreted as code. - * - * Note, for performance reasons: only import this file if - * `HardcodedDataInterpretedAsCode::Configuration` is needed, - * otherwise `HardcodedDataInterpretedAsCodeCustomizations` should be - * imported instead. - */ +/** DEPRECATED. Import `HardcodedDataInterpretedAsCodeQuery` instead. */ import javascript +private import HardcodedDataInterpretedAsCodeQuery as HardcodedDataInterpretedAsCodeQuery // ignore-query-import -module HardcodedDataInterpretedAsCode { - import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode - - /** - * A taint-tracking configuration for reasoning about hard-coded data - * being interpreted as code - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "HardcodedDataInterpretedAsCode" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { - source.(Source).getLabel() = lbl - } - - override predicate isSink(DataFlow::Node nd, DataFlow::FlowLabel lbl) { - nd.(Sink).getLabel() = lbl - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } -} +/** DEPRECATED. Import `HardcodedDataInterpretedAsCodeQuery` instead. */ +deprecated module HardcodedDataInterpretedAsCode = HardcodedDataInterpretedAsCodeQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll new file mode 100644 index 00000000000..7318681a882 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll @@ -0,0 +1,30 @@ +/** + * Provides a taint-tracking configuration for reasoning about hard-coded data + * being interpreted as code. + * + * Note, for performance reasons: only import this file if + * `HardcodedDataInterpretedAsCode::Configuration` is needed, + * otherwise `HardcodedDataInterpretedAsCodeCustomizations` should be + * imported instead. + */ + +import javascript +import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode + +/** + * A taint-tracking configuration for reasoning about hard-coded data + * being interpreted as code + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "HardcodedDataInterpretedAsCode" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) { + source.(Source).getLabel() = lbl + } + + override predicate isSink(DataFlow::Node nd, DataFlow::FlowLabel lbl) { + nd.(Sink).getLabel() = lbl + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll index f59a40dd9d8..18f90400e3d 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll @@ -1,26 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about host header - * poisoning in email generation. - */ +/** DEPRECATED. Import `HostHeaderPoisoningInEmailGenerationQuery` instead. */ import javascript +private import HostHeaderPoisoningInEmailGenerationQuery as HostHeaderPoisoningInEmailGenerationQuery // ignore-query-import -module HostHeaderPoisoningInEmailGeneration { - /** - * A taint tracking configuration for host header poisoning in email generation. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "TaintedHostHeader" } - - override predicate isSource(DataFlow::Node node) { - exists(HTTP::RequestHeaderAccess input | node = input | - input.getKind() = "header" and - input.getAHeaderName() = "host" - ) - } - - override predicate isSink(DataFlow::Node node) { - exists(EmailSender email | node = email.getABody()) - } - } -} +/** DEPRECATED. Import `HostHeaderPoisoningInEmailGenerationQuery` instead. */ +deprecated module HostHeaderPoisoningInEmailGeneration = HostHeaderPoisoningInEmailGenerationQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll new file mode 100644 index 00000000000..2a41b76dc80 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll @@ -0,0 +1,24 @@ +/** + * Provides a taint tracking configuration for reasoning about host header + * poisoning in email generation. + */ + +import javascript + +/** + * A taint tracking configuration for host header poisoning in email generation. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "TaintedHostHeader" } + + override predicate isSource(DataFlow::Node node) { + exists(HTTP::RequestHeaderAccess input | node = input | + input.getKind() = "header" and + input.getAHeaderName() = "host" + ) + } + + override predicate isSink(DataFlow::Node node) { + exists(EmailSender email | node = email.getABody()) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll index 55cf85d36a6..0569ba0e692 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll @@ -1,29 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about writing user-controlled data to files. - * - * Note, for performance reasons: only import this file if - * `HttpToFileAccess::Configuration` is needed, otherwise - * `HttpToFileAccessCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `HttpToFileAccessQuery` instead. */ import javascript +private import HttpToFileAccessQuery as HttpToFileAccessQuery // ignore-query-import -module HttpToFileAccess { - import HttpToFileAccessCustomizations::HttpToFileAccess - - /** - * A taint tracking configuration for writing user-controlled data to files. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "HttpToFileAccess" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `HttpToFileAccessQuery` instead. */ +deprecated module HttpToFileAccess = HttpToFileAccessQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll new file mode 100644 index 00000000000..cb756cccbc2 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll @@ -0,0 +1,26 @@ +/** + * Provides a taint tracking configuration for reasoning about writing user-controlled data to files. + * + * Note, for performance reasons: only import this file if + * `HttpToFileAccess::Configuration` is needed, otherwise + * `HttpToFileAccessCustomizations` should be imported instead. + */ + +import javascript +import HttpToFileAccessCustomizations::HttpToFileAccess + +/** + * A taint tracking configuration for writing user-controlled data to files. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "HttpToFileAccess" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll index ebe7c1b834f..7b221c4edb5 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about improper code - * sanitization. - * - * Note, for performance reasons: only import this file if - * `ImproperCodeSanitization::Configuration` is needed, otherwise - * `ImproperCodeSanitizationCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ImproperCodeSanitizationQuery` instead. */ import javascript +private import ImproperCodeSanitizationQuery as ImproperCodeSanitizationQuery // ignore-query-import -/** - * Classes and predicates for reasoning about improper code sanitization. - */ -module ImproperCodeSanitization { - import ImproperCodeSanitizationCustomizations::ImproperCodeSanitization - - /** - * A taint-tracking configuration for reasoning about improper code sanitization vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ImproperCodeSanitization" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof Sanitizer } - } -} +/** DEPRECATED. Import `ImproperCodeSanitizationQuery` instead. */ +deprecated module ImproperCodeSanitization = ImproperCodeSanitizationQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll new file mode 100644 index 00000000000..fd68b3a7077 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll @@ -0,0 +1,24 @@ +/** + * Provides a taint-tracking configuration for reasoning about improper code + * sanitization. + * + * Note, for performance reasons: only import this file if + * `ImproperCodeSanitization::Configuration` is needed, otherwise + * `ImproperCodeSanitizationCustomizations` should be imported instead. + */ + +import javascript +import ImproperCodeSanitizationCustomizations::ImproperCodeSanitization + +/** + * A taint-tracking configuration for reasoning about improper code sanitization vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ImproperCodeSanitization" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof Sanitizer } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll index 523e42f6b00..f036a3388df 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll @@ -1,58 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * incomplete HTML sanitization vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `IncompleteHtmlAttributeSanitization::Configuration` is needed, otherwise - * `IncompleteHtmlAttributeSanitizationCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `IncompleteHtmlAttributeSanitizationQuery` instead. */ import javascript +private import IncompleteHtmlAttributeSanitizationQuery as IncompleteHtmlAttributeSanitizationQuery // ignore-query-import -module IncompleteHtmlAttributeSanitization { - import IncompleteHtmlAttributeSanitizationCustomizations::IncompleteHtmlAttributeSanitization - - private module Label { - class Quote extends DataFlow::FlowLabel { - Quote() { this = ["\"", "'"] } - } - - class Ampersand extends DataFlow::FlowLabel { - Ampersand() { this = "&" } - } - - DataFlow::FlowLabel characterToLabel(string c) { c = result } - } - - /** - * A taint-tracking configuration for reasoning about incomplete HTML sanitization vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "IncompleteHtmlAttributeSanitization" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - label = Label::characterToLabel(source.(Source).getAnUnsanitizedCharacter()) - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - label = Label::characterToLabel(sink.(Sink).getADangerousCharacter()) - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - super.isAdditionalFlowStep(src, dst) and srclabel = dstlabel - } - - override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { - lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or - isSanitizer(node) - } - - override predicate isSanitizer(DataFlow::Node n) { - n instanceof Sanitizer or - super.isSanitizer(n) - } - } -} +/** DEPRECATED. Import `IncompleteHtmlAttributeSanitizationQuery` instead. */ +deprecated module IncompleteHtmlAttributeSanitization = IncompleteHtmlAttributeSanitizationQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll new file mode 100644 index 00000000000..b7920a9054d --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll @@ -0,0 +1,55 @@ +/** + * Provides a taint tracking configuration for reasoning about + * incomplete HTML sanitization vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `IncompleteHtmlAttributeSanitization::Configuration` is needed, otherwise + * `IncompleteHtmlAttributeSanitizationCustomizations` should be imported instead. + */ + +import javascript +import IncompleteHtmlAttributeSanitizationCustomizations::IncompleteHtmlAttributeSanitization + +private module Label { + class Quote extends DataFlow::FlowLabel { + Quote() { this = ["\"", "'"] } + } + + class Ampersand extends DataFlow::FlowLabel { + Ampersand() { this = "&" } + } + + DataFlow::FlowLabel characterToLabel(string c) { c = result } +} + +/** + * A taint-tracking configuration for reasoning about incomplete HTML sanitization vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "IncompleteHtmlAttributeSanitization" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + label = Label::characterToLabel(source.(Source).getAnUnsanitizedCharacter()) + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + label = Label::characterToLabel(sink.(Sink).getADangerousCharacter()) + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + super.isAdditionalFlowStep(src, dst) and srclabel = dstlabel + } + + override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { + lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or + isSanitizer(node) + } + + override predicate isSanitizer(DataFlow::Node n) { + n instanceof Sanitizer or + super.isSanitizer(n) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll index 35bee0d0cf9..64e24b9ceba 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll @@ -1,38 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about command-injection - * vulnerabilities (CWE-078). - */ +/** DEPRECATED. Import `IndirectCommandInjectionQuery` instead. */ import javascript +private import IndirectCommandInjectionQuery as IndirectCommandInjectionQuery // ignore-query-import -module IndirectCommandInjection { - import IndirectCommandInjectionCustomizations::IndirectCommandInjection - private import IndirectCommandArgument - - /** - * A taint-tracking configuration for reasoning about command-injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "IndirectCommandInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - /** - * Holds if `sink` is a data-flow sink for command-injection vulnerabilities, and - * the alert should be placed at the node `highlight`. - */ - predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { - sink instanceof Sink and highlight = sink - or - isIndirectCommandArgument(sink, highlight) - } - - 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) - } - } -} +/** DEPRECATED. Import `IndirectCommandInjectionQuery` instead. */ +deprecated module IndirectCommandInjection = IndirectCommandInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll new file mode 100644 index 00000000000..4d6745db931 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll @@ -0,0 +1,35 @@ +/** + * Provides a taint-tracking configuration for reasoning about command-injection + * vulnerabilities (CWE-078). + */ + +import javascript +import IndirectCommandInjectionCustomizations::IndirectCommandInjection +private import IndirectCommandArgument + +/** + * A taint-tracking configuration for reasoning about command-injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "IndirectCommandInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + /** + * Holds if `sink` is a data-flow sink for command-injection vulnerabilities, and + * the alert should be placed at the node `highlight`. + */ + predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { + sink instanceof Sink and highlight = sink + or + isIndirectCommandArgument(sink, highlight) + } + + 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/InsecureDownload.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll index 6fb12060d65..83c1d179243 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll @@ -1,40 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about download of sensitive file through insecure connection. - * - * Note, for performance reasons: only import this file if - * `InsecureDownload::Configuration` is needed, otherwise - * `InsecureDownloadCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `InsecureDownloadQuery` instead. */ import javascript +private import InsecureDownloadQuery as InsecureDownloadQuery // ignore-query-import -/** - * Classes and predicates for reasoning about download of sensitive file through insecure connection vulnerabilities. - */ -module InsecureDownload { - import InsecureDownloadCustomizations::InsecureDownload - - // Materialize flow labels - private class ConcreteSensitiveInsecureURL extends Label::SensitiveInsecureURL { - ConcreteSensitiveInsecureURL() { this = this } - } - - private class ConcreteInsecureURL extends Label::InsecureURL { - ConcreteInsecureURL() { this = this } - } - - /** - * A taint tracking configuration for download of sensitive file through insecure connection. - */ - class Configuration extends DataFlow::Configuration { - Configuration() { this = "InsecureDownload" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getALabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink.(Sink).getALabel() = label - } - } -} +/** DEPRECATED. Import `InsecureDownloadQuery` instead. */ +deprecated module InsecureDownload = InsecureDownloadQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll new file mode 100644 index 00000000000..d61c2f6a626 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll @@ -0,0 +1,34 @@ +/** + * Provides a taint tracking configuration for reasoning about download of sensitive file through insecure connection. + * + * Note, for performance reasons: only import this file if + * `InsecureDownload::Configuration` is needed, otherwise + * `InsecureDownloadCustomizations` should be imported instead. + */ + +import javascript +import InsecureDownloadCustomizations::InsecureDownload + +// Materialize flow labels +private class ConcreteSensitiveInsecureURL extends Label::SensitiveInsecureURL { + ConcreteSensitiveInsecureURL() { this = this } +} + +private class ConcreteInsecureURL extends Label::InsecureURL { + ConcreteInsecureURL() { this = this } +} + +/** + * A taint tracking configuration for download of sensitive file through insecure connection. + */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "InsecureDownload" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getALabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(Sink).getALabel() = label + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll index 4d60cd441bd..2672d48bee7 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll @@ -1,42 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about random - * values that are not cryptographically secure. - * - * Note, for performance reasons: only import this file if - * `InsecureRandomness::Configuration` is needed, otherwise - * `InsecureRandomnessCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `InsecureRandomnessQuery` instead. */ import javascript -private import semmle.javascript.security.SensitiveActions +private import InsecureRandomnessQuery as InsecureRandomnessQuery // ignore-query-import -module InsecureRandomness { - import InsecureRandomnessCustomizations::InsecureRandomness - - /** - * A taint tracking configuration for random values that are not cryptographically secure. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "InsecureRandomness" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - // not making use of `super.isSanitizer`: those sanitizers are not for this kind of data - node instanceof Sanitizer - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - // stop propagation at the sinks to avoid double reporting - pred instanceof Sink and - // constrain succ - pred = succ.getAPredecessor() - } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - InsecureRandomness::isAdditionalTaintStep(pred, succ) - } - } -} +/** DEPRECATED. Import `InsecureRandomnessQuery` instead. */ +deprecated module InsecureRandomness = InsecureRandomnessQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll new file mode 100644 index 00000000000..436430498ed --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll @@ -0,0 +1,39 @@ +/** + * Provides a taint tracking configuration for reasoning about random + * values that are not cryptographically secure. + * + * Note, for performance reasons: only import this file if + * `InsecureRandomness::Configuration` is needed, otherwise + * `InsecureRandomnessCustomizations` should be imported instead. + */ + +import javascript +private import semmle.javascript.security.SensitiveActions +import InsecureRandomnessCustomizations::InsecureRandomness + +/** + * A taint tracking configuration for random values that are not cryptographically secure. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "InsecureRandomness" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + // not making use of `super.isSanitizer`: those sanitizers are not for this kind of data + node instanceof Sanitizer + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + // stop propagation at the sinks to avoid double reporting + pred instanceof Sink and + // constrain succ + pred = succ.getAPredecessor() + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + InsecureRandomness::isAdditionalTaintStep(pred, succ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll index eb313bda425..f3d814e3601 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll @@ -1,36 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * password hashing with insufficient computational effort. - * - * Note, for performance reasons: only import this file if - * `InsufficientPasswordHash::Configuration` is needed, otherwise - * `InsufficientPasswordHashCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `InsufficientPasswordHashQuery` instead. */ import javascript +private import InsufficientPasswordHashQuery as InsufficientPasswordHashQuery // ignore-query-import -module InsufficientPasswordHash { - import InsufficientPasswordHashCustomizations::InsufficientPasswordHash - - /** - * A taint tracking configuration for password hashing with insufficient computational effort. - * - * This configuration identifies flows from `Source`s, which are sources of - * password data, to `Sink`s, which is an abstract class representing all - * the places password data may be hashed with insufficient computational effort. Additional sources or sinks can be - * added either by extending the relevant class, or by subclassing this configuration itself, - * and amending the sources and sinks. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "InsufficientPasswordHash" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `InsufficientPasswordHashQuery` instead. */ +deprecated module InsufficientPasswordHash = InsufficientPasswordHashQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll new file mode 100644 index 00000000000..40bfcc1072b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll @@ -0,0 +1,33 @@ +/** + * Provides a taint tracking configuration for reasoning about + * password hashing with insufficient computational effort. + * + * Note, for performance reasons: only import this file if + * `InsufficientPasswordHash::Configuration` is needed, otherwise + * `InsufficientPasswordHashCustomizations` should be imported instead. + */ + +import javascript +import InsufficientPasswordHashCustomizations::InsufficientPasswordHash + +/** + * A taint tracking configuration for password hashing with insufficient computational effort. + * + * This configuration identifies flows from `Source`s, which are sources of + * password data, to `Sink`s, which is an abstract class representing all + * the places password data may be hashed with insufficient computational effort. Additional sources or sinks can be + * added either by extending the relevant class, or by subclassing this configuration itself, + * and amending the sources and sinks. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "InsufficientPasswordHash" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll index 265b978d4a3..95dec6e87fd 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll @@ -1,77 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about untrusted user input used in log entries. - */ +/** DEPRECATED. Import `LogInjectionQuery` instead. */ import javascript +private import LogInjectionQuery as LogInjectionQuery // ignore-query-import -/** - * 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. - */ - abstract class Source extends DataFlow::Node { } - - /** - * A data flow sink for user input used in log entries. - */ - abstract class Sink extends DataFlow::Node { } - - /** - * A sanitizer for malicious user input used in log entries. - */ - abstract class Sanitizer extends DataFlow::Node { } - - /** - * A taint-tracking configuration for untrusted user input used in log entries. - */ - class LogInjectionConfiguration extends TaintTracking::Configuration { - LogInjectionConfiguration() { this = "LogInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } - - /** - * A source of remote user controlled input. - */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource and not this instanceof ClientSideRemoteFlowSource - } - } - - /** - * An argument to a logging mechanism. - */ - class LoggingSink extends Sink { - LoggingSink() { this = any(LoggerCall console).getAMessageComponent() } - } - - /** - * A call to `String.prototype.replace` that replaces `\n` is considered to sanitize the replaced string (reduce false positive). - */ - class StringReplaceSanitizer extends Sanitizer { - StringReplaceSanitizer() { - exists(string s | this.(StringReplaceCall).replaces(s, "") and s.regexpMatch("\\n")) - } - } - - /** - * A call to an HTML sanitizer is considered to sanitize the user input. - */ - class HtmlSanitizer extends Sanitizer { - HtmlSanitizer() { this instanceof HtmlSanitizerCall } - } - - /** - * A call to `JSON.stringify` or similar, seen as sanitizing log output. - */ - class JsonStringifySanitizer extends Sanitizer { - JsonStringifySanitizer() { this = any(JsonStringifyCall c).getOutput() } - } -} +/** DEPRECATED. Import `LogInjectionQuery` instead. */ +deprecated module LogInjection = LogInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll new file mode 100644 index 00000000000..2cdfc2ed9f7 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll @@ -0,0 +1,72 @@ +/** + * Provides a taint-tracking configuration for reasoning about untrusted user input used in log entries. + */ + +import javascript + +/** + * A data flow source for user input used in log entries. + */ +abstract class Source extends DataFlow::Node { } + +/** + * A data flow sink for user input used in log entries. + */ +abstract class Sink extends DataFlow::Node { } + +/** + * A sanitizer for malicious user input used in log entries. + */ +abstract class Sanitizer extends DataFlow::Node { } + +/** + * A taint-tracking configuration for untrusted user input used in log entries. + */ +class LogInjectionConfiguration extends TaintTracking::Configuration { + LogInjectionConfiguration() { this = "LogInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * A source of remote user controlled input. + */ +class RemoteSource extends Source { + RemoteSource() { + this instanceof RemoteFlowSource and not this instanceof ClientSideRemoteFlowSource + } +} + +/** + * An argument to a logging mechanism. + */ +class LoggingSink extends Sink { + LoggingSink() { this = any(LoggerCall console).getAMessageComponent() } +} + +/** + * A call to `String.prototype.replace` that replaces `\n` is considered to sanitize the replaced string (reduce false positive). + */ +class StringReplaceSanitizer extends Sanitizer { + StringReplaceSanitizer() { + exists(string s | this.(StringReplaceCall).replaces(s, "") and s.regexpMatch("\\n")) + } +} + +/** + * A call to an HTML sanitizer is considered to sanitize the user input. + */ +class HtmlSanitizer extends Sanitizer { + HtmlSanitizer() { this instanceof HtmlSanitizerCall } +} + +/** + * A call to `JSON.stringify` or similar, seen as sanitizing log output. + */ +class JsonStringifySanitizer extends Sanitizer { + JsonStringifySanitizer() { this = any(JsonStringifyCall c).getOutput() } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll index f1da1f78c09..ab65fb9705e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll @@ -1,43 +1,8 @@ -/** - * Provides a taint tracking configuration for reasoning about DoS attacks - * using a user-controlled object with an unbounded .length property. - * - * Note, for performance reasons: only import this file if - * `LoopBoundInjection::Configuration` is needed, otherwise - * `LoopBoundInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `LoopBoundInjectionQuery` instead. */ import javascript import semmle.javascript.security.TaintedObject +private import LoopBoundInjectionQuery as LoopBoundInjectionQuery // ignore-query-import -module LoopBoundInjection { - import LoopBoundInjectionCustomizations::LoopBoundInjection - - /** - * A taint tracking configuration for reasoning about looping on tainted objects with unbounded length. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "LoopBoundInjection" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source instanceof Source and label = TaintedObject::label() - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink instanceof Sink and label = TaintedObject::label() - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TaintedObject::SanitizerGuard or - guard instanceof IsArraySanitizerGuard or - guard instanceof InstanceofArraySanitizerGuard or - guard instanceof LengthCheckSanitizerGuard - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedObject::step(src, trg, inlbl, outlbl) - } - } -} +/** DEPRECATED. Import `LoopBoundInjectionQuery` instead. */ +deprecated module LoopBoundInjection = LoopBoundInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll new file mode 100644 index 00000000000..165f96f7f29 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll @@ -0,0 +1,40 @@ +/** + * Provides a taint tracking configuration for reasoning about DoS attacks + * using a user-controlled object with an unbounded .length property. + * + * Note, for performance reasons: only import this file if + * `LoopBoundInjection::Configuration` is needed, otherwise + * `LoopBoundInjectionCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.TaintedObject +import LoopBoundInjectionCustomizations::LoopBoundInjection + +/** + * A taint tracking configuration for reasoning about looping on tainted objects with unbounded length. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "LoopBoundInjection" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source instanceof Source and label = TaintedObject::label() + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof Sink and label = TaintedObject::label() + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard or + guard instanceof IsArraySanitizerGuard or + guard instanceof InstanceofArraySanitizerGuard or + guard instanceof LengthCheckSanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, trg, inlbl, outlbl) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll index d539bb09d40..8534cad9a7e 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll @@ -1,56 +1,8 @@ -/** - * Provides a taint tracking configuration for reasoning about NoSQL - * injection vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `NosqlInjection::Configuration` is needed, otherwise - * `NosqlInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `NosqlInjectionQuery` instead. */ import javascript import semmle.javascript.security.TaintedObject +private import NosqlInjectionQuery as NosqlInjectionQuery // ignore-query-import -module NosqlInjection { - import NosqlInjectionCustomizations::NosqlInjection - - /** - * A taint-tracking configuration for reasoning about SQL-injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "NosqlInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - TaintedObject::isSource(source, label) - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink.(Sink).getAFlowLabel() = label - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TaintedObject::SanitizerGuard - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedObject::step(src, trg, inlbl, outlbl) - or - // additional flow step to track taint through NoSQL query objects - inlbl = TaintedObject::label() and - outlbl = TaintedObject::label() and - exists(NoSQL::Query query, DataFlow::SourceNode queryObj | - queryObj.flowsToExpr(query) and - queryObj.flowsTo(trg) and - src = queryObj.getAPropertyWrite().getRhs() - ) - } - } -} +/** DEPRECATED. Import `NosqlInjectionQuery` instead. */ +deprecated module NosqlInjection = NosqlInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll new file mode 100644 index 00000000000..0da389208f2 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll @@ -0,0 +1,53 @@ +/** + * Provides a taint tracking configuration for reasoning about NoSQL + * injection vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `NosqlInjection::Configuration` is needed, otherwise + * `NosqlInjectionCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.TaintedObject +import NosqlInjectionCustomizations::NosqlInjection + +/** + * A taint-tracking configuration for reasoning about SQL-injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "NosqlInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + TaintedObject::isSource(source, label) + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(Sink).getAFlowLabel() = label + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, trg, inlbl, outlbl) + or + // additional flow step to track taint through NoSQL query objects + inlbl = TaintedObject::label() and + outlbl = TaintedObject::label() and + exists(NoSQL::Query query, DataFlow::SourceNode queryObj | + queryObj.flowsToExpr(query) and + queryObj.flowsTo(trg) and + src = queryObj.getAPropertyWrite().getRhs() + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll index f5095cb74f1..392466f32ab 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll @@ -1,68 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * cross-window communication with unrestricted origin. - * - * Note, for performance reasons: only import this file if - * `PostMessageStar::Configuration` is needed, otherwise - * `PostMessageStarCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `PostMessageStarQuery` instead. */ import javascript +private import PostMessageStarQuery as PostMessageStarQuery // ignore-query-import -module PostMessageStar { - import PostMessageStarCustomizations::PostMessageStar - - // Materialize flow labels - private class ConcretePartiallyTaintedObject extends PartiallyTaintedObject { - ConcretePartiallyTaintedObject() { this = this } - } - - /** - * A taint tracking configuration for cross-window communication with unrestricted origin. - * - * This configuration identifies flows from `Source`s, which are sources of - * sensitive data, to `Sink`s, which is an abstract class representing all - * the places sensitive data may be transmitted across window boundaries without restricting - * the origin. - * - * Additional sources or sinks can be added either by extending the relevant class, or by subclassing - * this configuration itself, and amending the sources and sinks. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "PostMessageStar" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { - sink instanceof Sink and lbl = anyLabel() - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - // writing a tainted value to an object property makes the object partially tainted - exists(DataFlow::PropWrite write | - write.getRhs() = src and - inlbl = anyLabel() and - trg.(DataFlow::SourceNode).flowsTo(write.getBase()) and - outlbl instanceof PartiallyTaintedObject - ) - or - // `toString` or `JSON.toString` on a partially tainted object gives a tainted value - exists(DataFlow::InvokeNode toString | toString = trg | - toString.(DataFlow::MethodCallNode).calls(src, "toString") - or - src = toString.(JsonStringifyCall).getInput() - ) and - inlbl instanceof PartiallyTaintedObject and - outlbl.isTaint() - or - // `valueOf` preserves partial taint - trg.(DataFlow::MethodCallNode).calls(src, "valueOf") and - inlbl instanceof PartiallyTaintedObject and - outlbl = inlbl - } - } -} +/** DEPRECATED. Import `PostMessageStarQuery` instead. */ +deprecated module PostMessageStar = PostMessageStarQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll new file mode 100644 index 00000000000..ae7366146da --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll @@ -0,0 +1,65 @@ +/** + * Provides a taint tracking configuration for reasoning about + * cross-window communication with unrestricted origin. + * + * Note, for performance reasons: only import this file if + * `PostMessageStar::Configuration` is needed, otherwise + * `PostMessageStarCustomizations` should be imported instead. + */ + +import javascript +import PostMessageStarCustomizations::PostMessageStar + +// Materialize flow labels +private class ConcretePartiallyTaintedObject extends PartiallyTaintedObject { + ConcretePartiallyTaintedObject() { this = this } +} + +/** + * A taint tracking configuration for cross-window communication with unrestricted origin. + * + * This configuration identifies flows from `Source`s, which are sources of + * sensitive data, to `Sink`s, which is an abstract class representing all + * the places sensitive data may be transmitted across window boundaries without restricting + * the origin. + * + * Additional sources or sinks can be added either by extending the relevant class, or by subclassing + * this configuration itself, and amending the sources and sinks. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "PostMessageStar" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) { + sink instanceof Sink and lbl = anyLabel() + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + // writing a tainted value to an object property makes the object partially tainted + exists(DataFlow::PropWrite write | + write.getRhs() = src and + inlbl = anyLabel() and + trg.(DataFlow::SourceNode).flowsTo(write.getBase()) and + outlbl instanceof PartiallyTaintedObject + ) + or + // `toString` or `JSON.toString` on a partially tainted object gives a tainted value + exists(DataFlow::InvokeNode toString | toString = trg | + toString.(DataFlow::MethodCallNode).calls(src, "toString") + or + src = toString.(JsonStringifyCall).getInput() + ) and + inlbl instanceof PartiallyTaintedObject and + outlbl.isTaint() + or + // `valueOf` preserves partial taint + trg.(DataFlow::MethodCallNode).calls(src, "valueOf") and + inlbl instanceof PartiallyTaintedObject and + outlbl = inlbl + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll index c6fc119190e..6663d74e91a 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll @@ -1,209 +1,6 @@ -/** - * 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. - */ +/** DEPRECATED. Import `PrototypePollutingAssignmentQuery` instead. */ -private import javascript -private import semmle.javascript.DynamicPropertyAccess -private import semmle.javascript.dataflow.InferredTypes +private import PrototypePollutingAssignmentQuery as PrototypePollutingAssignmentQuery // ignore-query-import -/** - * Provides a taint tracking configuration for reasoning about - * prototype-polluting assignments. - */ -module PrototypePollutingAssignment { - private import PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment - - // Materialize flow labels - private class ConcreteObjectPrototype extends ObjectPrototype { - ConcreteObjectPrototype() { this = this } - } - - /** 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(DynamicPropRead read | - pred = read.getPropertyNameNode() 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.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) { - super.isLabeledBarrier(node, lbl) - or - // Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype. - node instanceof DataFlow::ThisNode 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 TypeofCheck 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 SharedFlowSteps to track a bit further - exists(DataFlow::Node mid | - prototypeLessObject(t.continue()).flowsTo(mid) and - DataFlow::SharedFlowStep::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() { - 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 - 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 check of form `typeof e === "string"`. */ - private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { - override EqualityTest astNode; - Expr operand; - boolean polarity; - - TypeofCheck() { - exists(TypeofTag value | TaintTracking::isTypeofGuard(astNode, operand, value) | - value = "object" and polarity = astNode.getPolarity().booleanNot() - or - value != "object" and polarity = astNode.getPolarity() - ) - } - - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { - polarity = outcome 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") } - - 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() - } - } -} +/** DEPRECATED. Import `PrototypePollutingAssignmentQuery` instead. */ +deprecated module PrototypePollutingAssignment = PrototypePollutingAssignmentQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll new file mode 100644 index 00000000000..2c55bc6a8eb --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll @@ -0,0 +1,200 @@ +/** + * 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 +private import semmle.javascript.dataflow.InferredTypes +private import PrototypePollutingAssignmentCustomizations::PrototypePollutingAssignment + +// Materialize flow labels +private class ConcreteObjectPrototype extends ObjectPrototype { + ConcreteObjectPrototype() { this = this } +} + +/** 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(DynamicPropRead read | + pred = read.getPropertyNameNode() 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.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) { + super.isLabeledBarrier(node, lbl) + or + // Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype. + node instanceof DataFlow::ThisNode 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 TypeofCheck 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 SharedFlowSteps to track a bit further + exists(DataFlow::Node mid | + prototypeLessObject(t.continue()).flowsTo(mid) and + DataFlow::SharedFlowStep::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() { + 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 + 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 check of form `typeof e === "string"`. */ +private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + Expr operand; + boolean polarity; + + TypeofCheck() { + exists(TypeofTag value | TaintTracking::isTypeofGuard(astNode, operand, value) | + value = "object" and polarity = astNode.getPolarity().booleanNot() + or + value != "object" and polarity = astNode.getPolarity() + ) + } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + polarity = outcome 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") } + + 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/PrototypePollution.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollution.qll index 7667f128d08..7783a551775 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollution.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollution.qll @@ -1,56 +1,10 @@ -/** - * Provides a taint-tracking configuration for tracking - * user-controlled objects flowing into a vulnerable `extends` call. - * - * Note, for performance reasons: only import this file if - * `PrototypePollution::Configuration` is needed, otherwise - * `PrototypePollutionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `PrototypePollutionQuery` instead. */ import javascript import semmle.javascript.security.TaintedObject import semmle.javascript.dependencies.Dependencies import semmle.javascript.dependencies.SemVer +private import PrototypePollutionQuery as PrototypePollutionQuery // ignore-query-import -module PrototypePollution { - import PrototypePollutionCustomizations::PrototypePollution - - // Materialize flow labels - private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapper { - ConcreteTaintedObjectWrapper() { this = this } - } - - /** - * A taint tracking configuration for user-controlled objects flowing into deep `extend` calls, - * leading to prototype pollution. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "PrototypePollution" } - - override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) { - node.(Source).getAFlowLabel() = label - } - - override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel label) { - node.(Sink).getAFlowLabel() = label - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedObject::step(src, dst, inlbl, outlbl) - or - // Track objects are wrapped in other objects - exists(DataFlow::PropWrite write | - src = write.getRhs() and - inlbl = TaintedObject::label() and - dst = write.getBase().getALocalSource() and - outlbl = TaintedObjectWrapper::label() - ) - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { - node instanceof TaintedObject::SanitizerGuard - } - } -} +/** DEPRECATED. Import `PrototypePollutionQuery` instead. */ +deprecated module PrototypePollution = PrototypePollutionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll new file mode 100644 index 00000000000..165b3ffc07b --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll @@ -0,0 +1,53 @@ +/** + * Provides a taint-tracking configuration for tracking + * user-controlled objects flowing into a vulnerable `extends` call. + * + * Note, for performance reasons: only import this file if + * `PrototypePollution::Configuration` is needed, otherwise + * `PrototypePollutionCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.TaintedObject +import semmle.javascript.dependencies.Dependencies +import semmle.javascript.dependencies.SemVer +import PrototypePollutionCustomizations::PrototypePollution + +// Materialize flow labels +private class ConcreteTaintedObjectWrapper extends TaintedObjectWrapper { + ConcreteTaintedObjectWrapper() { this = this } +} + +/** + * A taint tracking configuration for user-controlled objects flowing into deep `extend` calls, + * leading to prototype pollution. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "PrototypePollution" } + + override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) { + node.(Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel label) { + node.(Sink).getAFlowLabel() = label + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, dst, inlbl, outlbl) + or + // Track objects are wrapped in other objects + exists(DataFlow::PropWrite write | + src = write.getRhs() and + inlbl = TaintedObject::label() and + dst = write.getBase().getALocalSource() and + outlbl = TaintedObjectWrapper::label() + ) + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { + node instanceof TaintedObject::SanitizerGuard + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll index b7034996a63..92ffd84fdda 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about reflected - * cross-site scripting vulnerabilities. - */ +/** DEPRECATED. Import `ReflectedXssQuery` instead. */ import javascript +private import ReflectedXssQuery as ReflectedXssQuery // ignore-query-import -module ReflectedXss { - import ReflectedXssCustomizations::ReflectedXss - - /** - * A taint-tracking configuration for reasoning about XSS. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ReflectedXss" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof SanitizerGuard - } - } -} +/** DEPRECATED. Import `ReflectedXssQuery` instead. */ +deprecated module ReflectedXss = ReflectedXssQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll new file mode 100644 index 00000000000..b6f0c886f4d --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint-tracking configuration for reasoning about reflected + * cross-site scripting vulnerabilities. + */ + +import javascript +import ReflectedXssCustomizations::ReflectedXss + +/** + * A taint-tracking configuration for reasoning about XSS. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ReflectedXss" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof SanitizerGuard + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll index b6644ab6ffe..c1a27c66354 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * untrusted user input used to construct regular expressions. - * - * Note, for performance reasons: only import this file if - * `RegExpInjection::Configuration` is needed, otherwise - * `RegExpInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `RegExpInjectionQuery` instead. */ import javascript +private import RegExpInjectionQuery as RegExpInjectionQuery // ignore-query-import -module RegExpInjection { - import RegExpInjectionCustomizations::RegExpInjection - - /** - * A taint-tracking configuration for untrusted user input used to construct regular expressions. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "RegExpInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `RegExpInjectionQuery` instead. */ +deprecated module RegExpInjection = RegExpInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll new file mode 100644 index 00000000000..00fe3779e12 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * untrusted user input used to construct regular expressions. + * + * Note, for performance reasons: only import this file if + * `RegExpInjection::Configuration` is needed, otherwise + * `RegExpInjectionCustomizations` should be imported instead. + */ + +import javascript +import RegExpInjectionCustomizations::RegExpInjection + +/** + * A taint-tracking configuration for untrusted user input used to construct regular expressions. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "RegExpInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll index 6c9f80bf96d..f19b02fdcb3 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll @@ -1,32 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about injections in - * property names, used either for writing into a property, into a header or - * for calling an object's method. - * - * Note, for performance reasons: only import this file if - * `RemotePropertyInjection::Configuration` is needed, otherwise - * `RemotePropertyInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `RemotePropertyInjectionQuery` instead. */ import javascript +private import RemotePropertyInjectionQuery as RemotePropertyInjectionQuery // ignore-query-import -module RemotePropertyInjection { - import RemotePropertyInjectionCustomizations::RemotePropertyInjection - - /** - * A taint-tracking configuration for reasoning about remote property injection. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "RemotePropertyInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer or - node = StringConcatenation::getRoot(any(ConstantString str).flow()) - } - } -} +/** DEPRECATED. Import `RemotePropertyInjectionQuery` instead. */ +deprecated module RemotePropertyInjection = RemotePropertyInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll new file mode 100644 index 00000000000..83422e8f0de --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll @@ -0,0 +1,29 @@ +/** + * Provides a taint tracking configuration for reasoning about injections in + * property names, used either for writing into a property, into a header or + * for calling an object's method. + * + * Note, for performance reasons: only import this file if + * `RemotePropertyInjection::Configuration` is needed, otherwise + * `RemotePropertyInjectionCustomizations` should be imported instead. + */ + +import javascript +import RemotePropertyInjectionCustomizations::RemotePropertyInjection + +/** + * A taint-tracking configuration for reasoning about remote property injection. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "RemotePropertyInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer or + node = StringConcatenation::getRoot(any(ConstantString str).flow()) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll index 99c5300469b..a4612bf360d 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll @@ -1,39 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about request - * forgery. - * - * Note, for performance reasons: only import this file if - * `RequestForgery::Configuration` is needed, otherwise - * `RequestForgeryCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `RequestForgeryQuery` instead. */ import javascript import UrlConcatenation +private import RequestForgeryQuery as RequestForgeryQuery // ignore-query-import -module RequestForgery { - import RequestForgeryCustomizations::RequestForgery - - /** - * A taint tracking configuration for request forgery. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "RequestForgery" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { - sanitizingPrefixEdge(source, sink) - } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - isAdditionalRequestForgeryStep(pred, succ) - } - } -} +/** DEPRECATED. Import `RequestForgeryQuery` instead. */ +deprecated module RequestForgery = RequestForgeryQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll new file mode 100644 index 00000000000..e5107e7c2e9 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll @@ -0,0 +1,36 @@ +/** + * Provides a taint-tracking configuration for reasoning about request + * forgery. + * + * Note, for performance reasons: only import this file if + * `RequestForgery::Configuration` is needed, otherwise + * `RequestForgeryCustomizations` should be imported instead. + */ + +import javascript +import UrlConcatenation +import RequestForgeryCustomizations::RequestForgery + +/** + * A taint tracking configuration for request forgery. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "RequestForgery" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { + sanitizingPrefixEdge(source, sink) + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + isAdditionalRequestForgeryStep(pred, succ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll index f2d6cfb1652..25d27e77f2f 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll @@ -1,41 +1,9 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * unvalidated URL redirection problems on the server side. - * - * Note, for performance reasons: only import this file if - * `ServerSideUrlRedirect::Configuration` is needed, otherwise - * `ServerSideUrlRedirectCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ServerSideUrlRedirectQuery` instead. */ import javascript import RemoteFlowSources import UrlConcatenation +private import ServerSideUrlRedirectQuery as ServerSideUrlRedirectQuery // ignore-query-import -module ServerSideUrlRedirect { - import ServerSideUrlRedirectCustomizations::ServerSideUrlRedirect - - /** - * A taint-tracking configuration for reasoning about unvalidated URL redirections. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ServerSideUrlRedirect" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { - hostnameSanitizingPrefixEdge(source, sink) - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof LocalUrlSanitizingGuard or - guard instanceof HostnameSanitizerGuard - } - } -} +/** DEPRECATED. Import `ServerSideUrlRedirectQuery` instead. */ +deprecated module ServerSideUrlRedirect = ServerSideUrlRedirectQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll new file mode 100644 index 00000000000..982c1da7272 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll @@ -0,0 +1,38 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * unvalidated URL redirection problems on the server side. + * + * Note, for performance reasons: only import this file if + * `ServerSideUrlRedirect::Configuration` is needed, otherwise + * `ServerSideUrlRedirectCustomizations` should be imported instead. + */ + +import javascript +import RemoteFlowSources +import UrlConcatenation +import ServerSideUrlRedirectCustomizations::ServerSideUrlRedirect + +/** + * A taint-tracking configuration for reasoning about unvalidated URL redirections. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ServerSideUrlRedirect" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerEdge(DataFlow::Node source, DataFlow::Node sink) { + hostnameSanitizingPrefixEdge(source, sink) + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof LocalUrlSanitizingGuard or + guard instanceof HostnameSanitizerGuard + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll index a47f593612f..af1c0e7a574 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll @@ -1,34 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * command-injection vulnerabilities (CWE-078). - * - * Note, for performance reasons: only import this file if - * `ShellCommandInjectionFromEnvironment::Configuration` is needed, otherwise - * `ShellCommandInjectionFromEnvironmentCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ShellCommandInjectionFromEnvironmentQuery` instead. */ import javascript +private import ShellCommandInjectionFromEnvironmentQuery as ShellCommandInjectionFromEnvironmentQuery // ignore-query-import -module ShellCommandInjectionFromEnvironment { - import ShellCommandInjectionFromEnvironmentCustomizations::ShellCommandInjectionFromEnvironment - import IndirectCommandArgument - - /** - * A taint-tracking configuration for reasoning about command-injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "ShellCommandInjectionFromEnvironment" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { - sink instanceof Sink and highlight = sink - or - isIndirectCommandArgument(sink, highlight) - } - - override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - } -} +/** DEPRECATED. Import `ShellCommandInjectionFromEnvironmentQuery` instead. */ +deprecated module ShellCommandInjectionFromEnvironment = ShellCommandInjectionFromEnvironmentQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll new file mode 100644 index 00000000000..c8366dd2bd9 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll @@ -0,0 +1,31 @@ +/** + * Provides a taint tracking configuration for reasoning about + * command-injection vulnerabilities (CWE-078). + * + * Note, for performance reasons: only import this file if + * `ShellCommandInjectionFromEnvironment::Configuration` is needed, otherwise + * `ShellCommandInjectionFromEnvironmentCustomizations` should be imported instead. + */ + +import javascript +import ShellCommandInjectionFromEnvironmentCustomizations::ShellCommandInjectionFromEnvironment +import IndirectCommandArgument + +/** + * A taint-tracking configuration for reasoning about command-injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "ShellCommandInjectionFromEnvironment" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { + sink instanceof Sink and highlight = sink + or + isIndirectCommandArgument(sink, highlight) + } + + override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll index 51ec162f4d8..32b0d80669b 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about string based - * query injection vulnerabilities - * - * Note, for performance reasons: only import this file if - * `SqlInjection::Configuration` is needed, otherwise - * `SqlInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `SqlInjectionQuery` instead. */ import javascript +private import SqlInjectionQuery as SqlInjectionQuery // ignore-query-import -module SqlInjection { - import SqlInjectionCustomizations::SqlInjection - - /** - * A taint-tracking configuration for reasoning about string based query injection vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "SqlInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `SqlInjectionQuery` instead. */ +deprecated module SqlInjection = SqlInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll new file mode 100644 index 00000000000..0adbf564fb0 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint tracking configuration for reasoning about string based + * query injection vulnerabilities + * + * Note, for performance reasons: only import this file if + * `SqlInjection::Configuration` is needed, otherwise + * `SqlInjectionCustomizations` should be imported instead. + */ + +import javascript +import SqlInjectionCustomizations::SqlInjection + +/** + * A taint-tracking configuration for reasoning about string based query injection vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "SqlInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll b/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll index e787557d913..4211c6fd633 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll @@ -1,38 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about stack - * trace exposure problems. - * - * Note, for performance reasons: only import this file if - * `StackTraceExposure::Configuration` is needed, otherwise - * `StackTraceExposureCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `StackTraceExposureQuery` instead. */ import javascript +private import StackTraceExposureQuery as StackTraceExposureQuery // ignore-query-import -module StackTraceExposure { - import StackTraceExposureCustomizations::StackTraceExposure - - /** - * A taint-tracking configuration for reasoning about stack trace - * exposure problems. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "StackTraceExposure" } - - override predicate isSource(DataFlow::Node src) { src instanceof Source } - - override predicate isSanitizer(DataFlow::Node nd) { - super.isSanitizer(nd) - or - // read of a property other than `stack` - nd.(DataFlow::PropRead).getPropertyName() != "stack" - or - // `toString` does not include the stack trace - nd.(DataFlow::MethodCallNode).getMethodName() = "toString" - or - nd = StringConcatenation::getAnOperand(_) - } - - override predicate isSink(DataFlow::Node snk) { snk instanceof Sink } - } -} +/** DEPRECATED. Import `StackTraceExposureQuery` instead. */ +deprecated module StackTraceExposure = StackTraceExposureQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll new file mode 100644 index 00000000000..4350fbab061 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll @@ -0,0 +1,35 @@ +/** + * Provides a taint-tracking configuration for reasoning about stack + * trace exposure problems. + * + * Note, for performance reasons: only import this file if + * `StackTraceExposure::Configuration` is needed, otherwise + * `StackTraceExposureCustomizations` should be imported instead. + */ + +import javascript +import StackTraceExposureCustomizations::StackTraceExposure + +/** + * A taint-tracking configuration for reasoning about stack trace + * exposure problems. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "StackTraceExposure" } + + override predicate isSource(DataFlow::Node src) { src instanceof Source } + + override predicate isSanitizer(DataFlow::Node nd) { + super.isSanitizer(nd) + or + // read of a property other than `stack` + nd.(DataFlow::PropRead).getPropertyName() != "stack" + or + // `toString` does not include the stack trace + nd.(DataFlow::MethodCallNode).getMethodName() = "toString" + or + nd = StringConcatenation::getAnOperand(_) + } + + override predicate isSink(DataFlow::Node snk) { snk instanceof Sink } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll index 9fbf0933042..65536440bcb 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll @@ -1,40 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about stored - * cross-site scripting vulnerabilities. - */ +/** DEPRECATED. Import `StoredXssQuery` instead. */ import javascript +private import StoredXssQuery as StoredXssQuery // ignore-query-import -module StoredXss { - import Xss::StoredXss - - /** - * A taint-tracking configuration for reasoning about XSS. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "StoredXss" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof SanitizerGuard - } - } - - /** A file name, considered as a flow source for stored XSS. */ - class FileNameSourceAsSource extends Source { - FileNameSourceAsSource() { this instanceof FileNameSource } - } - - /** User-controlled torrent information, considered as a flow source for stored XSS. */ - class UserControlledTorrentInfoAsSource extends Source { - UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo } - } -} +/** DEPRECATED. Import `StoredXssQuery` instead. */ +deprecated module StoredXss = StoredXssQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll new file mode 100644 index 00000000000..654b609a23a --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll @@ -0,0 +1,37 @@ +/** + * Provides a taint-tracking configuration for reasoning about stored + * cross-site scripting vulnerabilities. + */ + +import javascript +import Xss::StoredXss + +/** + * A taint-tracking configuration for reasoning about XSS. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "StoredXss" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof SanitizerGuard + } +} + +/** A file name, considered as a flow source for stored XSS. */ +class FileNameSourceAsSource extends Source { + FileNameSourceAsSource() { this instanceof FileNameSource } +} + +/** User-controlled torrent information, considered as a flow source for stored XSS. */ +class UserControlledTorrentInfoAsSource extends Source { + UserControlledTorrentInfoAsSource() { this instanceof ParseTorrent::UserControlledTorrentInfo } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll index f80f6054187..a0660580206 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll @@ -1,32 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about format - * injections. - * - * - * Note, for performance reasons: only import this file if - * `TaintedFormatString::Configuration` is needed, otherwise - * `TaintedFormatStringCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `TaintedFormatStringQuery` instead. */ import javascript import semmle.javascript.security.dataflow.DOM +private import TaintedFormatStringQuery as TaintedFormatStringQuery // ignore-query-import -module TaintedFormatString { - import TaintedFormatStringCustomizations::TaintedFormatString - - /** - * A taint-tracking configuration for format injections. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "TaintedFormatString" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `TaintedFormatStringQuery` instead. */ +deprecated module TaintedFormatString = TaintedFormatStringQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll new file mode 100644 index 00000000000..5810b70da17 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll @@ -0,0 +1,29 @@ +/** + * Provides a taint-tracking configuration for reasoning about format + * injections. + * + * + * Note, for performance reasons: only import this file if + * `TaintedFormatString::Configuration` is needed, otherwise + * `TaintedFormatStringCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.DOM +import TaintedFormatStringCustomizations::TaintedFormatString + +/** + * A taint-tracking configuration for format injections. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "TaintedFormatString" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll index 37efbb5347e..ffd7d320684 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll @@ -1,54 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * tainted-path vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `TaintedPath::Configuration` is needed, otherwise - * `TaintedPathCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `TaintedPathQuery` instead. */ import javascript +private import TaintedPathQuery as TaintedPathQuery // ignore-query-import -module TaintedPath { - import TaintedPathCustomizations::TaintedPath - - // Materialize flow labels - private class ConcretePosixPath extends Label::PosixPath { - ConcretePosixPath() { this = this } - } - - private class ConcreteSplitPath extends Label::SplitPath { - ConcreteSplitPath() { this = this } - } - - /** - * A taint-tracking configuration for reasoning about tainted-path vulnerabilities. - */ - class Configuration extends DataFlow::Configuration { - Configuration() { this = "TaintedPath" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - label = source.(Source).getAFlowLabel() - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - label = sink.(Sink).getAFlowLabel() - } - - override predicate isBarrier(DataFlow::Node node) { - super.isBarrier(node) or - node instanceof Sanitizer - } - - override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) { - guard instanceof BarrierGuardNode - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - isAdditionalTaintedPathFlowStep(src, dst, srclabel, dstlabel) - } - } -} +/** DEPRECATED. Import `TaintedPathQuery` instead. */ +deprecated module TaintedPath = TaintedPathQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll new file mode 100644 index 00000000000..914c63543f5 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll @@ -0,0 +1,51 @@ +/** + * Provides a taint tracking configuration for reasoning about + * tainted-path vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `TaintedPath::Configuration` is needed, otherwise + * `TaintedPathCustomizations` should be imported instead. + */ + +import javascript +import TaintedPathCustomizations::TaintedPath + +// Materialize flow labels +private class ConcretePosixPath extends Label::PosixPath { + ConcretePosixPath() { this = this } +} + +private class ConcreteSplitPath extends Label::SplitPath { + ConcreteSplitPath() { this = this } +} + +/** + * A taint-tracking configuration for reasoning about tainted-path vulnerabilities. + */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "TaintedPath" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + label = source.(Source).getAFlowLabel() + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + label = sink.(Sink).getAFlowLabel() + } + + override predicate isBarrier(DataFlow::Node node) { + super.isBarrier(node) or + node instanceof Sanitizer + } + + override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) { + guard instanceof BarrierGuardNode + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + isAdditionalTaintedPathFlowStep(src, dst, srclabel, dstlabel) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll index 52028eb104f..37f3721d600 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll @@ -1,45 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * template object injection vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `TemplateObjectInjection::Configuration` is needed, otherwise - * `TemplateObjectInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `TemplateObjectInjectionQuery` instead. */ import javascript +private import TemplateObjectInjectionQuery as TemplateObjectInjectionQuery // ignore-query-import -/** - * Provides a taint tracking configuration for reasoning template object injection vulnerabilities. - */ -module TemplateObjectInjection { - import TemplateObjectInjectionCustomizations::TemplateObjectInjection - private import semmle.javascript.security.TaintedObject - - /** - * A taint tracking configuration for reasoning about template object injection vulnerabilities. - */ - class TemplateObjInjectionConfig extends TaintTracking::Configuration { - TemplateObjInjectionConfig() { this = "TemplateObjInjectionConfig" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getAFlowLabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink instanceof Sink and label = TaintedObject::label() - } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TaintedObject::SanitizerGuard - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl - ) { - TaintedObject::step(src, trg, inlbl, outlbl) - } - } -} +/** DEPRECATED. Import `TemplateObjectInjectionQuery` instead. */ +deprecated module TemplateObjectInjection = TemplateObjectInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll new file mode 100644 index 00000000000..22bb06e4af3 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll @@ -0,0 +1,39 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * template object injection vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `TemplateObjectInjection::Configuration` is needed, otherwise + * `TemplateObjectInjectionCustomizations` should be imported instead. + */ + +import javascript +import TemplateObjectInjectionCustomizations::TemplateObjectInjection +private import semmle.javascript.security.TaintedObject + +/** + * A taint tracking configuration for reasoning about template object injection vulnerabilities. + */ +class TemplateObjInjectionConfig extends TaintTracking::Configuration { + TemplateObjInjectionConfig() { this = "TemplateObjInjectionConfig" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getAFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink instanceof Sink and label = TaintedObject::label() + } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TaintedObject::SanitizerGuard + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node trg, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + TaintedObject::step(src, trg, inlbl, outlbl) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll index 41dc7bafffa..44744e0efa3 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll @@ -1,33 +1,8 @@ -/** - * Provides a tracking configuration for reasoning about type - * confusion for HTTP request inputs. - * - * Note, for performance reasons: only import this file if - * `TypeConfusionThroughParameterTampering::Configuration` is needed, - * otherwise `TypeConfusionThroughParameterTamperingCustomizations` - * should be imported instead. - */ +/** DEPRECATED. Import `TypeConfusionThroughParameterTamperingQuery` instead. */ import javascript -private import semmle.javascript.dataflow.InferredTypes +private import TypeConfusionThroughParameterTamperingQuery as TypeConfusionThroughParameterTamperingQuery // ignore-query-import -module TypeConfusionThroughParameterTampering { - import TypeConfusionThroughParameterTamperingCustomizations::TypeConfusionThroughParameterTampering - - /** - * A taint tracking configuration for type confusion for HTTP request inputs. - */ - class Configuration extends DataFlow::Configuration { - Configuration() { this = "TypeConfusionThroughParameterTampering" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { - sink instanceof Sink and - sink.analyze().getAType() = TTString() and - sink.analyze().getAType() = TTObject() - } - - override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier } - } -} +/** DEPRECATED. Import `TypeConfusionThroughParameterTamperingQuery` instead. */ +deprecated module TypeConfusionThroughParameterTampering = + TypeConfusionThroughParameterTamperingQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll new file mode 100644 index 00000000000..da6b698d97f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll @@ -0,0 +1,30 @@ +/** + * Provides a tracking configuration for reasoning about type + * confusion for HTTP request inputs. + * + * Note, for performance reasons: only import this file if + * `TypeConfusionThroughParameterTampering::Configuration` is needed, + * otherwise `TypeConfusionThroughParameterTamperingCustomizations` + * should be imported instead. + */ + +import javascript +private import semmle.javascript.dataflow.InferredTypes +import TypeConfusionThroughParameterTamperingCustomizations::TypeConfusionThroughParameterTampering + +/** + * A taint tracking configuration for type confusion for HTTP request inputs. + */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "TypeConfusionThroughParameterTampering" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof Sink and + sink.analyze().getAType() = TTString() and + sink.analyze().getAType() = TTObject() + } + + override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll index 31ceef258a2..d3695f42f78 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll @@ -1,30 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about unsafe deserialization. - * - * Note, for performance reasons: only import this file if - * `UnsafeDeserialization::Configuration` is needed, otherwise - * `UnsafeDeserializationCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `UnsafeDeserializationQuery` instead. */ import javascript import semmle.javascript.security.dataflow.RemoteFlowSources +private import UnsafeDeserializationQuery as UnsafeDeserializationQuery // ignore-query-import -module UnsafeDeserialization { - import UnsafeDeserializationCustomizations::UnsafeDeserialization - - /** - * A taint-tracking configuration for reasoning about unsafe deserialization. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnsafeDeserialization" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `UnsafeDeserializationQuery` instead. */ +deprecated module UnsafeDeserialization = UnsafeDeserializationQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll new file mode 100644 index 00000000000..66e55852fb0 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint-tracking configuration for reasoning about unsafe deserialization. + * + * Note, for performance reasons: only import this file if + * `UnsafeDeserialization::Configuration` is needed, otherwise + * `UnsafeDeserializationCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.RemoteFlowSources +import UnsafeDeserializationCustomizations::UnsafeDeserialization + +/** + * A taint-tracking configuration for reasoning about unsafe deserialization. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnsafeDeserialization" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll index 9e17e9d2ce4..c38bb4cdeb8 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll @@ -1,75 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about method invocations - * with a user-controlled method name on objects with unsafe methods. - * - * Note, for performance reasons: only import this file if - * `UnsafeDynamicMethodAccess::Configuration` is needed, otherwise - * `UnsafeDynamicMethodAccessCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `UnsafeDynamicMethodAccessQuery` instead. */ import javascript import PropertyInjectionShared +private import UnsafeDynamicMethodAccessQuery as UnsafeDynamicMethodAccessQuery // ignore-query-import -module UnsafeDynamicMethodAccess { - private import DataFlow::FlowLabel - import UnsafeDynamicMethodAccessCustomizations::UnsafeDynamicMethodAccess - - // Materialize flow labels - private class ConcreteUnsafeFunction extends UnsafeFunction { - ConcreteUnsafeFunction() { this = this } - } - - /** - * A taint-tracking configuration for reasoning about unsafe dynamic method access. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnsafeDynamicMethodAccess" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getFlowLabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink.(Sink).getFlowLabel() = label - } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) - or - node instanceof Sanitizer - or - exists(StringConcatenation::getOperand(node, _)) and - not StringConcatenation::isCoercion(node) - } - - /** - * Holds if a property of the given object is an unsafe function. - */ - predicate hasUnsafeMethods(DataFlow::SourceNode node) { - PropertyInjection::hasUnsafeMethods(node) // Redefined here so custom queries can override it - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - // Reading a property of the global object or of a function - exists(DataFlow::PropRead read | - hasUnsafeMethods(read.getBase().getALocalSource()) and - src = read.getPropertyNameExpr().flow() and - dst = read and - srclabel.isTaint() and - dstlabel = unsafeFunction() - ) - or - // Reading a chain of properties from any object with a prototype can lead to Function - exists(PropertyProjection proj | - not PropertyInjection::isPrototypeLessObject(proj.getObject().getALocalSource()) and - src = proj.getASelector() and - dst = proj and - srclabel.isTaint() and - dstlabel = unsafeFunction() - ) - } - } -} +/** DEPRECATED. Import `UnsafeDynamicMethodAccessQuery` instead. */ +deprecated module UnsafeDynamicMethodAccess = UnsafeDynamicMethodAccessQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll new file mode 100644 index 00000000000..4386a21fcce --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll @@ -0,0 +1,72 @@ +/** + * Provides a taint-tracking configuration for reasoning about method invocations + * with a user-controlled method name on objects with unsafe methods. + * + * Note, for performance reasons: only import this file if + * `UnsafeDynamicMethodAccess::Configuration` is needed, otherwise + * `UnsafeDynamicMethodAccessCustomizations` should be imported instead. + */ + +import javascript +import PropertyInjectionShared +private import DataFlow::FlowLabel +import UnsafeDynamicMethodAccessCustomizations::UnsafeDynamicMethodAccess + +// Materialize flow labels +private class ConcreteUnsafeFunction extends UnsafeFunction { + ConcreteUnsafeFunction() { this = this } +} + +/** + * A taint-tracking configuration for reasoning about unsafe dynamic method access. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnsafeDynamicMethodAccess" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(Sink).getFlowLabel() = label + } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof Sanitizer + or + exists(StringConcatenation::getOperand(node, _)) and + not StringConcatenation::isCoercion(node) + } + + /** + * Holds if a property of the given object is an unsafe function. + */ + predicate hasUnsafeMethods(DataFlow::SourceNode node) { + PropertyInjection::hasUnsafeMethods(node) // Redefined here so custom queries can override it + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + // Reading a property of the global object or of a function + exists(DataFlow::PropRead read | + hasUnsafeMethods(read.getBase().getALocalSource()) and + src = read.getPropertyNameExpr().flow() and + dst = read and + srclabel.isTaint() and + dstlabel = unsafeFunction() + ) + or + // Reading a chain of properties from any object with a prototype can lead to Function + exists(PropertyProjection proj | + not PropertyInjection::isPrototypeLessObject(proj.getObject().getALocalSource()) and + src = proj.getASelector() and + dst = proj and + srclabel.isTaint() and + dstlabel = unsafeFunction() + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll index 4fe675b16d9..8617d3e8724 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll @@ -1,48 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * unsafe HTML constructed from library input vulnerabilities. - */ +/** DEPRECATED. Import `UnsafeHtmlConstructionQuery` instead. */ import javascript +private import UnsafeHtmlConstructionQuery as UnsafeHtmlConstructionQuery // ignore-query-import -/** - * Classes and predicates for the unsafe HTML constructed from library input query. - */ -module UnsafeHtmlConstruction { - private import semmle.javascript.security.dataflow.DomBasedXssCustomizations::DomBasedXss as DomBasedXss - private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQueryPlugin - import UnsafeHtmlConstructionCustomizations::UnsafeHtmlConstruction - - /** - * A taint-tracking configuration for reasoning about unsafe HTML constructed from library input vulnerabilities. - */ - class Configration extends TaintTracking::Configuration { - Configration() { this = "UnsafeHtmlConstruction" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) - or - node instanceof DomBasedXss::Sanitizer - or - node instanceof UnsafeJQueryPlugin::Sanitizer - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - DomBasedXss::isOptionallySanitizedEdge(pred, succ) - } - - // override to require that there is a path without unmatched return steps - override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { - super.hasFlowPath(source, sink) and - DataFlow::hasPathWithoutUnmatchedReturn(source, sink) - } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - DataFlow::localFieldStep(pred, succ) - } - } -} +/** DEPRECATED. Import `UnsafeHtmlConstructionQuery` instead. */ +deprecated module UnsafeHtmlConstruction = UnsafeHtmlConstructionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll new file mode 100644 index 00000000000..56af9ad7ab3 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll @@ -0,0 +1,42 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * unsafe HTML constructed from library input vulnerabilities. + */ + +import javascript +private import semmle.javascript.security.dataflow.DomBasedXssCustomizations::DomBasedXss as DomBasedXss +private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQueryPlugin +import UnsafeHtmlConstructionCustomizations::UnsafeHtmlConstruction + +/** + * A taint-tracking configuration for reasoning about unsafe HTML constructed from library input vulnerabilities. + */ +class Configration extends TaintTracking::Configuration { + Configration() { this = "UnsafeHtmlConstruction" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof DomBasedXss::Sanitizer + or + node instanceof UnsafeJQueryPlugin::Sanitizer + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + DomBasedXss::isOptionallySanitizedEdge(pred, succ) + } + + // override to require that there is a path without unmatched return steps + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + super.hasFlowPath(source, sink) and + DataFlow::hasPathWithoutUnmatchedReturn(source, sink) + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + DataFlow::localFieldStep(pred, succ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll index 05c33b71330..634b7d917aa 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll @@ -1,87 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about DOM-based - * cross-site scripting vulnerabilities in unsafe jQuery plugins. - */ +/** DEPRECATED. Import `UnsafeJQueryPluginQuery` instead. */ import javascript import semmle.javascript.security.dataflow.Xss +private import UnsafeJQueryPluginQuery as UnsafeJQueryPluginQuery // ignore-query-import -module UnsafeJQueryPlugin { - import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin - - /** - * A taint-tracking configuration for reasoning about XSS in unsafe jQuery plugins. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnsafeJQueryPlugin" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) - or - node instanceof DomBasedXss::Sanitizer - or - node instanceof Sanitizer - } - - override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { - // jQuery plugins tend to be implemented as classes that store data in fields initialized by the constructor. - DataFlow::localFieldStep(src, sink) or - aliasPropertyPresenceStep(src, sink) - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - // prefixing prevents forced html/css confusion: - // prefixing through concatenation: - StringConcatenation::taintStep(pred, succ, _, any(int i | i >= 1)) - or - // prefixing through a poor-mans templating system: - exists(StringReplaceCall replace | - replace = succ and - pred = replace.getRawReplacement() - ) - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { - super.isSanitizerGuard(node) or - node instanceof IsElementSanitizer or - node instanceof PropertyPresenceSanitizer - } - } - - /** - * Holds if there is a taint-step from `src` to `sink`, - * where `src` is a property read that acts as a sanitizer for the base, - * and `sink` is that same property read from the same base. - * - * For an condition like `if(foo.bar) {...}`, the base `foo` is sanitized but the property `foo.bar` is not. - * With this taint-step we regain that `foo.bar` is tainted, because `PropertyPresenceSanitizer` could remove it. - */ - private predicate aliasPropertyPresenceStep(DataFlow::Node src, DataFlow::Node sink) { - exists(ReachableBasicBlock srcBB, ReachableBasicBlock sinkBB | - aliasPropertyPresenceStepHelper(src, sink, srcBB, sinkBB) and - srcBB.strictlyDominates(sinkBB) - ) - } - - /** - * Holds if there is a taint-step from `src` to `sink`, and `srcBB` is the basicblock for `src` and `sinkBB` is the basicblock for `sink`. - * - * This predicate is outlined to get a better join-order. - */ - pragma[noinline] - private predicate aliasPropertyPresenceStepHelper( - DataFlow::PropRead src, DataFlow::Node sink, ReachableBasicBlock srcBB, - ReachableBasicBlock sinkBB - ) { - exists(PropertyPresenceSanitizer sanitizer | - src = sanitizer.getPropRead() and - sink = AccessPath::getAnAliasedSourceNode(src) and - srcBB = src.getBasicBlock() and - sinkBB = sink.getBasicBlock() - ) - } -} +/** DEPRECATED. Import `UnsafeJQueryPluginQuery` instead. */ +deprecated module UnsafeJQueryPlugin = UnsafeJQueryPluginQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll new file mode 100644 index 00000000000..a84e7474ea3 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll @@ -0,0 +1,83 @@ +/** + * Provides a taint-tracking configuration for reasoning about DOM-based + * cross-site scripting vulnerabilities in unsafe jQuery plugins. + */ + +import javascript +import semmle.javascript.security.dataflow.Xss +import UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin + +/** + * A taint-tracking configuration for reasoning about XSS in unsafe jQuery plugins. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnsafeJQueryPlugin" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) + or + node instanceof DomBasedXss::Sanitizer + or + node instanceof Sanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { + // jQuery plugins tend to be implemented as classes that store data in fields initialized by the constructor. + DataFlow::localFieldStep(src, sink) or + aliasPropertyPresenceStep(src, sink) + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + // prefixing prevents forced html/css confusion: + // prefixing through concatenation: + StringConcatenation::taintStep(pred, succ, _, any(int i | i >= 1)) + or + // prefixing through a poor-mans templating system: + exists(StringReplaceCall replace | + replace = succ and + pred = replace.getRawReplacement() + ) + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) { + super.isSanitizerGuard(node) or + node instanceof IsElementSanitizer or + node instanceof PropertyPresenceSanitizer + } +} + +/** + * Holds if there is a taint-step from `src` to `sink`, + * where `src` is a property read that acts as a sanitizer for the base, + * and `sink` is that same property read from the same base. + * + * For an condition like `if(foo.bar) {...}`, the base `foo` is sanitized but the property `foo.bar` is not. + * With this taint-step we regain that `foo.bar` is tainted, because `PropertyPresenceSanitizer` could remove it. + */ +private predicate aliasPropertyPresenceStep(DataFlow::Node src, DataFlow::Node sink) { + exists(ReachableBasicBlock srcBB, ReachableBasicBlock sinkBB | + aliasPropertyPresenceStepHelper(src, sink, srcBB, sinkBB) and + srcBB.strictlyDominates(sinkBB) + ) +} + +/** + * Holds if there is a taint-step from `src` to `sink`, and `srcBB` is the basicblock for `src` and `sinkBB` is the basicblock for `sink`. + * + * This predicate is outlined to get a better join-order. + */ +pragma[noinline] +private predicate aliasPropertyPresenceStepHelper( + DataFlow::PropRead src, DataFlow::Node sink, ReachableBasicBlock srcBB, ReachableBasicBlock sinkBB +) { + exists(PropertyPresenceSanitizer sanitizer | + src = sanitizer.getPropRead() and + sink = AccessPath::getAnAliasedSourceNode(src) and + srcBB = src.getBasicBlock() and + sinkBB = sink.getBasicBlock() + ) +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll index d47b3696de6..7e9470a7334 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll @@ -1,45 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about shell command - * constructed from library input vulnerabilities (CWE-078). - * - * Note, for performance reasons: only import this file if - * `UnsafeShellCommandConstruction::Configuration` is needed, otherwise - * `UnsafeShellCommandConstructionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `UnsafeShellCommandConstructionQuery` instead. */ import javascript +private import UnsafeShellCommandConstructionQuery as UnsafeShellCommandConstructionQuery // ignore-query-import -/** - * Classes and predicates for the shell command constructed from library input query. - */ -module UnsafeShellCommandConstruction { - import UnsafeShellCommandConstructionCustomizations::UnsafeShellCommandConstruction - - /** - * A taint-tracking configuration for reasoning about shell command constructed from library input vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnsafeShellCommandConstruction" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof PathExistsSanitizerGuard or - guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer - } - - // override to require that there is a path without unmatched return steps - override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { - super.hasFlowPath(source, sink) and - DataFlow::hasPathWithoutUnmatchedReturn(source, sink) - } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - DataFlow::localFieldStep(pred, succ) - } - } -} +/** DEPRECATED. Import `UnsafeShellCommandConstructionQuery` instead. */ +deprecated module UnsafeShellCommandConstruction = UnsafeShellCommandConstructionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll new file mode 100644 index 00000000000..219731dcbde --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll @@ -0,0 +1,39 @@ +/** + * Provides a taint tracking configuration for reasoning about shell command + * constructed from library input vulnerabilities (CWE-078). + * + * Note, for performance reasons: only import this file if + * `UnsafeShellCommandConstruction::Configuration` is needed, otherwise + * `UnsafeShellCommandConstructionCustomizations` should be imported instead. + */ + +import javascript +import UnsafeShellCommandConstructionCustomizations::UnsafeShellCommandConstruction + +/** + * A taint-tracking configuration for reasoning about shell command constructed from library input vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnsafeShellCommandConstruction" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof PathExistsSanitizerGuard or + guard instanceof TaintTracking::AdHocWhitelistCheckSanitizer + } + + // override to require that there is a path without unmatched return steps + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + super.hasFlowPath(source, sink) and + DataFlow::hasPathWithoutUnmatchedReturn(source, sink) + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + DataFlow::localFieldStep(pred, succ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll index 5075d29186b..f5af520e0d7 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll @@ -1,65 +1,9 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * unvalidated dynamic method calls. - * - * Note, for performance reasons: only import this file if - * `UnvalidatedDynamicMethodCall::Configuration` is needed, otherwise - * `UnvalidatedDynamicMethodCallCustomizations` should be imported - * instead. - */ +/** DEPRECATED. Import `UnvalidatedDynamicMethodCallQuery` instead. */ import javascript import semmle.javascript.frameworks.Express import PropertyInjectionShared -private import semmle.javascript.dataflow.InferredTypes +private import UnvalidatedDynamicMethodCallQuery as UnvalidatedDynamicMethodCallQuery // ignore-query-import -module UnvalidatedDynamicMethodCall { - import UnvalidatedDynamicMethodCallCustomizations::UnvalidatedDynamicMethodCall - private import DataFlow::FlowLabel - - // Materialize flow labels - private class ConcreteMaybeNonFunction extends MaybeNonFunction { - ConcreteMaybeNonFunction() { this = this } - } - - private class ConcreteMaybeFromProto extends MaybeFromProto { - ConcreteMaybeFromProto() { this = this } - } - - /** - * A taint-tracking configuration for reasoning about unvalidated dynamic method calls. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "UnvalidatedDynamicMethodCall" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - source.(Source).getFlowLabel() = label - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - sink.(Sink).getFlowLabel() = label - } - - override predicate isSanitizer(DataFlow::Node nd) { super.isSanitizer(nd) } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - exists(DataFlow::PropRead read | - src = read.getPropertyNameExpr().flow() and - dst = read and - srclabel.isTaint() and - ( - dstlabel instanceof MaybeNonFunction - or - // a property of `Object.create(null)` cannot come from a prototype - not PropertyInjection::isPrototypeLessObject(read.getBase().getALocalSource()) and - dstlabel instanceof MaybeFromProto - ) and - // avoid overlapping results with unsafe dynamic method access query - not PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource()) - ) - } - } -} +/** DEPRECATED. Import `UnvalidatedDynamicMethodCallQuery` instead. */ +deprecated module UnvalidatedDynamicMethodCall = UnvalidatedDynamicMethodCallQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll new file mode 100644 index 00000000000..e02a6288cdf --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll @@ -0,0 +1,62 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * unvalidated dynamic method calls. + * + * Note, for performance reasons: only import this file if + * `UnvalidatedDynamicMethodCall::Configuration` is needed, otherwise + * `UnvalidatedDynamicMethodCallCustomizations` should be imported + * instead. + */ + +import javascript +import semmle.javascript.frameworks.Express +import PropertyInjectionShared +private import semmle.javascript.dataflow.InferredTypes +import UnvalidatedDynamicMethodCallCustomizations::UnvalidatedDynamicMethodCall +private import DataFlow::FlowLabel + +// Materialize flow labels +private class ConcreteMaybeNonFunction extends MaybeNonFunction { + ConcreteMaybeNonFunction() { this = this } +} + +private class ConcreteMaybeFromProto extends MaybeFromProto { + ConcreteMaybeFromProto() { this = this } +} + +/** + * A taint-tracking configuration for reasoning about unvalidated dynamic method calls. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "UnvalidatedDynamicMethodCall" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + source.(Source).getFlowLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + sink.(Sink).getFlowLabel() = label + } + + override predicate isSanitizer(DataFlow::Node nd) { super.isSanitizer(nd) } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + exists(DataFlow::PropRead read | + src = read.getPropertyNameExpr().flow() and + dst = read and + srclabel.isTaint() and + ( + dstlabel instanceof MaybeNonFunction + or + // a property of `Object.create(null)` cannot come from a prototype + not PropertyInjection::isPrototypeLessObject(read.getBase().getALocalSource()) and + dstlabel instanceof MaybeFromProto + ) and + // avoid overlapping results with unsafe dynamic method access query + not PropertyInjection::hasUnsafeMethods(read.getBase().getALocalSource()) + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll index 62ce3b8a120..45615a92000 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about - * XML-bomb vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `XmlBomb::Configuration` is needed, otherwise - * `XmlBombCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `XmlBombQuery` instead. */ import javascript +private import XmlBombQuery as XmlBombQuery // ignore-query-import -module XmlBomb { - import XmlBombCustomizations::XmlBomb - - /** - * A taint-tracking configuration for reasoning about XML-bomb vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "XmlBomb" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `XmlBombQuery` instead. */ +deprecated module XmlBomb = XmlBombQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll new file mode 100644 index 00000000000..951b927f86e --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint tracking configuration for reasoning about + * XML-bomb vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `XmlBomb::Configuration` is needed, otherwise + * `XmlBombCustomizations` should be imported instead. + */ + +import javascript +import XmlBombCustomizations::XmlBomb + +/** + * A taint-tracking configuration for reasoning about XML-bomb vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "XmlBomb" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll index 4d782865afa..15f5413a620 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll @@ -1,31 +1,8 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * untrusted user input used in XPath expression. - * - * Note, for performance reasons: only import this file if - * `XpathInjection::Configuration` is needed, otherwise - * `XpathInjectionCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `XpathInjectionQuery` instead. */ import javascript import semmle.javascript.security.dataflow.DOM +private import XpathInjectionQuery as XpathInjectionQuery // ignore-query-import -module XpathInjection { - import XpathInjectionCustomizations::XpathInjection - - /** - * A taint-tracking configuration for untrusted user input used in XPath expression. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "XpathInjection" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `XpathInjectionQuery` instead. */ +deprecated module XpathInjection = XpathInjectionQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll new file mode 100644 index 00000000000..08e84e834d0 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll @@ -0,0 +1,28 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * untrusted user input used in XPath expression. + * + * Note, for performance reasons: only import this file if + * `XpathInjection::Configuration` is needed, otherwise + * `XpathInjectionCustomizations` should be imported instead. + */ + +import javascript +import semmle.javascript.security.dataflow.DOM +import XpathInjectionCustomizations::XpathInjection + +/** + * A taint-tracking configuration for untrusted user input used in XPath expression. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "XpathInjection" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll index f0f3c9d973c..0d3096d5c1b 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll @@ -1,43 +1,7 @@ -/** - * Provides a taint-tracking configuration for reasoning about - * cross-site scripting vulnerabilities through the DOM. - */ +/** DEPRECATED. Import `XssThroughDomQuery` instead. */ import javascript -private import semmle.javascript.dataflow.InferredTypes +private import XssThroughDomQuery as XssThroughDomQuery // ignore-query-import -/** - * Classes and predicates for the XSS through DOM query. - */ -module XssThroughDom { - import Xss::XssThroughDom - private import XssThroughDomCustomizations::XssThroughDom - private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss - private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery - - /** - * A taint-tracking configuration for reasoning about XSS through the DOM. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "XssThroughDOM" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof DomBasedXss::Sanitizer - } - - override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { - guard instanceof TypeTestGuard or - guard instanceof UnsafeJQuery::PropertyPresenceSanitizer or - guard instanceof DomBasedXss::SanitizerGuard - } - - override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - DomBasedXss::isOptionallySanitizedEdge(pred, succ) - } - } -} +/** DEPRECATED. Import `XssThroughDomQuery` instead. */ +deprecated module XssThroughDom = XssThroughDomQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll new file mode 100644 index 00000000000..258de0ff168 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll @@ -0,0 +1,37 @@ +/** + * Provides a taint-tracking configuration for reasoning about + * cross-site scripting vulnerabilities through the DOM. + */ + +import javascript +private import semmle.javascript.dataflow.InferredTypes +import Xss::XssThroughDom +private import XssThroughDomCustomizations::XssThroughDom +private import semmle.javascript.security.dataflow.Xss::DomBasedXss as DomBasedXss +private import semmle.javascript.security.dataflow.UnsafeJQueryPluginCustomizations::UnsafeJQueryPlugin as UnsafeJQuery + +/** + * A taint-tracking configuration for reasoning about XSS through the DOM. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "XssThroughDOM" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof DomBasedXss::Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof DomBasedXss::Sanitizer + } + + override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode guard) { + guard instanceof TypeTestGuard or + guard instanceof UnsafeJQuery::PropertyPresenceSanitizer or + guard instanceof DomBasedXss::SanitizerGuard + } + + override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { + DomBasedXss::isOptionallySanitizedEdge(pred, succ) + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll b/javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll index 307a850cd4d..5275c96bada 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll @@ -1,30 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about XML - * External Entity (XXE) vulnerabilities. - * - * Note, for performance reasons: only import this file if - * `Xxe::Configuration` is needed, otherwise `XxeCustomizations` - * should be imported instead. - */ +/** DEPRECATED. Import `XxeQuery` instead. */ import javascript +private import XxeQuery as XxeQuery // ignore-query-import -module Xxe { - import XxeCustomizations::Xxe - - /** - * A taint-tracking configuration for reasoning about XXE vulnerabilities. - */ - class Configuration extends TaintTracking::Configuration { - Configuration() { this = "Xxe" } - - override predicate isSource(DataFlow::Node source) { source instanceof Source } - - override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - - override predicate isSanitizer(DataFlow::Node node) { - super.isSanitizer(node) or - node instanceof Sanitizer - } - } -} +/** DEPRECATED. Import `XxeQuery` instead. */ +deprecated module Xxe = XxeQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll new file mode 100644 index 00000000000..82d3fb4f6cc --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll @@ -0,0 +1,27 @@ +/** + * Provides a taint tracking configuration for reasoning about XML + * External Entity (XXE) vulnerabilities. + * + * Note, for performance reasons: only import this file if + * `Xxe::Configuration` is needed, otherwise `XxeCustomizations` + * should be imported instead. + */ + +import javascript +import XxeCustomizations::Xxe + +/** + * A taint-tracking configuration for reasoning about XXE vulnerabilities. + */ +class Configuration extends TaintTracking::Configuration { + Configuration() { this = "Xxe" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + override predicate isSanitizer(DataFlow::Node node) { + super.isSanitizer(node) or + node instanceof Sanitizer + } +} diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll index cb41ee19791..cc3fd8a2f27 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll @@ -1,52 +1,7 @@ -/** - * Provides a taint tracking configuration for reasoning about unsafe - * zip and tar archive extraction. - * - * Note, for performance reasons: only import this file if - * `ZipSlip::Configuration` is needed, otherwise - * `ZipSlipCustomizations` should be imported instead. - */ +/** DEPRECATED. Import `ZipSlipQuery` instead. */ import javascript +private import ZipSlipQuery as ZipSlipQuery // ignore-query-import -module ZipSlip { - import ZipSlipCustomizations::ZipSlip - - // Materialize flow labels - private class ConcretePosixPath extends TaintedPath::Label::PosixPath { - ConcretePosixPath() { this = this } - } - - private class ConcreteSplitPath extends TaintedPath::Label::SplitPath { - ConcreteSplitPath() { this = this } - } - - /** A taint tracking configuration for unsafe archive extraction. */ - class Configuration extends DataFlow::Configuration { - Configuration() { this = "ZipSlip" } - - override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { - label = source.(Source).getAFlowLabel() - } - - override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { - label = sink.(Sink).getAFlowLabel() - } - - override predicate isBarrier(DataFlow::Node node) { - super.isBarrier(node) or - node instanceof TaintedPath::Sanitizer - } - - override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) { - guard instanceof TaintedPath::BarrierGuardNode - } - - override predicate isAdditionalFlowStep( - DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, - DataFlow::FlowLabel dstlabel - ) { - TaintedPath::isAdditionalTaintedPathFlowStep(src, dst, srclabel, dstlabel) - } - } -} +/** DEPRECATED. Import `ZipSlipQuery` instead. */ +deprecated module ZipSlip = ZipSlipQuery; diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll new file mode 100644 index 00000000000..9aad934759d --- /dev/null +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll @@ -0,0 +1,49 @@ +/** + * Provides a taint tracking configuration for reasoning about unsafe + * zip and tar archive extraction. + * + * Note, for performance reasons: only import this file if + * `ZipSlip::Configuration` is needed, otherwise + * `ZipSlipCustomizations` should be imported instead. + */ + +import javascript +import ZipSlipCustomizations::ZipSlip + +// Materialize flow labels +private class ConcretePosixPath extends TaintedPath::Label::PosixPath { + ConcretePosixPath() { this = this } +} + +private class ConcreteSplitPath extends TaintedPath::Label::SplitPath { + ConcreteSplitPath() { this = this } +} + +/** A taint tracking configuration for unsafe archive extraction. */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "ZipSlip" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) { + label = source.(Source).getAFlowLabel() + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) { + label = sink.(Sink).getAFlowLabel() + } + + override predicate isBarrier(DataFlow::Node node) { + super.isBarrier(node) or + node instanceof TaintedPath::Sanitizer + } + + override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) { + guard instanceof TaintedPath::BarrierGuardNode + } + + override predicate isAdditionalFlowStep( + DataFlow::Node src, DataFlow::Node dst, DataFlow::FlowLabel srclabel, + DataFlow::FlowLabel dstlabel + ) { + TaintedPath::isAdditionalTaintedPathFlowStep(src, dst, srclabel, dstlabel) + } +} From 5638a33199b7d3f093b07ed9b3934b0398451708 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 08:40:21 +0200 Subject: [PATCH 227/429] JS: Remove obsolete module prefix --- .../javascript/security/dataflow/CleartextLoggingQuery.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll index e651f21200c..e6e776db665 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll @@ -33,10 +33,10 @@ class Configuration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier } override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - CleartextLogging::isSanitizerEdge(pred, succ) + isSanitizerEdge(pred, succ) } override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { - CleartextLogging::isAdditionalTaintStep(src, trg) + isAdditionalTaintStep(src, trg) } } From abb819ed88eaf4c6f1ded1797f5ccc7f2872894b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 09:00:31 +0200 Subject: [PATCH 228/429] JS: Fix insecure randomness --- .../javascript/security/dataflow/InsecureRandomnessQuery.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll index 436430498ed..7911fa7c619 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll @@ -10,6 +10,7 @@ import javascript private import semmle.javascript.security.SensitiveActions import InsecureRandomnessCustomizations::InsecureRandomness +private import InsecureRandomnessCustomizations::InsecureRandomness as InsecureRandomness /** * A taint tracking configuration for random values that are not cryptographically secure. From 71930f93f1afe2c185f77b77e2f564e115d7701b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 09:14:00 +0200 Subject: [PATCH 229/429] JS: Fix cleartext logging --- .../javascript/security/dataflow/CleartextLoggingQuery.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll index e6e776db665..ca53cad67ec 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll @@ -9,6 +9,7 @@ import javascript import CleartextLoggingCustomizations::CleartextLogging +private import CleartextLoggingCustomizations::CleartextLogging as CleartextLogging /** * A taint tracking configuration for clear-text logging of sensitive information. @@ -33,10 +34,10 @@ class Configuration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier } override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - isSanitizerEdge(pred, succ) + CleartextLogging::isSanitizerEdge(pred, succ) } override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) { - isAdditionalTaintStep(src, trg) + CleartextLogging::isAdditionalTaintStep(src, trg) } } From 3a6da3445422fc488565b28cbb7d546e20005a1b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 09:39:57 +0200 Subject: [PATCH 230/429] JS: Add missing QLdoc --- .../dataflow/ShellCommandInjectionFromEnvironmentQuery.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll index c8366dd2bd9..787ae8625e4 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll @@ -19,6 +19,7 @@ class Configuration extends TaintTracking::Configuration { override predicate isSource(DataFlow::Node source) { source instanceof Source } + /** Holds if `sink` is a command-injection sink with `highlight` as the corresponding alert location. */ predicate isSinkWithHighlight(DataFlow::Node sink, DataFlow::Node highlight) { sink instanceof Sink and highlight = sink or From cb0075f15aa68a9a811d122b122f0d8a1305a0ad Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 10 Aug 2021 12:14:03 +0200 Subject: [PATCH 231/429] JS: Remove use of deprecated API --- .../ql/examples/queries/dataflow/StoredXss/StoredXss.ql | 6 +++--- .../queries/dataflow/StoredXss/StoredXssTypeTracking.ql | 6 +++--- javascript/ql/src/Security/CWE-089/SqlInjection.ql | 4 ++-- .../src/semmle/javascript/heuristics/AdditionalSinks.qll | 7 +++---- .../Security/CWE-338/InsecureRandomnessSource.ql | 2 +- javascript/ql/test/library-tests/frameworks/Vue/tests.ql | 5 +---- .../Security/CWE-022/TaintedPath/Consistency.ql | 2 +- .../Security/CWE-079/DomBasedXss/ConsistencyDomBasedXss.ql | 2 +- .../CWE-079/DomBasedXss/XssWithAdditionalSources.ql | 2 +- .../ReflectedXss/ReflectedXssWithCustomSanitizer.ql | 2 +- .../CWE-094/CodeInjection/HeuristicSourceCodeInjection.ql | 2 +- .../CWE-915/PrototypePollutingAssignment/Consistency.ql | 4 ++-- 12 files changed, 20 insertions(+), 24 deletions(-) diff --git a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql index 86ecf59e673..08d4abbcdd5 100644 --- a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql +++ b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql @@ -9,7 +9,7 @@ import javascript import DataFlow -import semmle.javascript.security.dataflow.StoredXss +import semmle.javascript.security.dataflow.StoredXssQuery import DataFlow::PathGraph /** @@ -21,7 +21,7 @@ import DataFlow::PathGraph * connection.query(..., (e, data) => { ... }); * ``` */ -class MysqlSource extends StoredXss::Source { +class MysqlSource extends Source { MysqlSource() { this = moduleImport("mysql") @@ -32,6 +32,6 @@ class MysqlSource extends StoredXss::Source { } } -from StoredXss::Configuration cfg, PathNode source, PathNode sink +from Configuration cfg, PathNode source, PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value." diff --git a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql index bca026cc2ae..39704bdc215 100644 --- a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql +++ b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql @@ -10,7 +10,7 @@ import javascript import DataFlow -import semmle.javascript.security.dataflow.StoredXss +import semmle.javascript.security.dataflow.StoredXssQuery import DataFlow::PathGraph /** @@ -42,10 +42,10 @@ DataFlow::SourceNode mysqlConnection() { result = mysqlConnection(DataFlow::Type * } * ``` */ -class MysqlSource extends StoredXss::Source { +class MysqlSource extends Source { MysqlSource() { this = mysqlConnection().getAMethodCall("query").getCallback(1).getParameter(1) } } -from StoredXss::Configuration cfg, PathNode source, PathNode sink +from Configuration cfg, PathNode source, PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value." diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql index 4aac9d9a1b7..cd68319c429 100644 --- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql +++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql @@ -12,8 +12,8 @@ */ import javascript -import semmle.javascript.security.dataflow.SqlInjection -import semmle.javascript.security.dataflow.NosqlInjection +import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection +import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection import DataFlow::PathGraph from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll b/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll index d1228c84248..da0d6a167f7 100644 --- a/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll +++ b/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll @@ -8,8 +8,7 @@ import javascript private import SyntacticHeuristics private import semmle.javascript.security.dataflow.CodeInjectionCustomizations private import semmle.javascript.security.dataflow.CommandInjectionCustomizations -private import semmle.javascript.security.dataflow.DomBasedXss as DomBasedXss -private import semmle.javascript.security.dataflow.ReflectedXss as ReflectedXss +private import semmle.javascript.security.dataflow.Xss as Xss private import semmle.javascript.security.dataflow.SqlInjectionCustomizations private import semmle.javascript.security.dataflow.NosqlInjectionCustomizations private import semmle.javascript.security.dataflow.TaintedPathCustomizations @@ -31,7 +30,7 @@ private class HeuristicCommandInjectionSink extends HeuristicSink, CommandInject } } -private class HeuristicDomBasedXssSink extends HeuristicSink, DomBasedXss::DomBasedXss::Sink { +private class HeuristicDomBasedXssSink extends HeuristicSink, Xss::DomBasedXss::Sink { HeuristicDomBasedXssSink() { isAssignedToOrConcatenatedWith(this, "(?i)(html|innerhtml)") or isArgTo(this, "(?i)(html|render)") or @@ -40,7 +39,7 @@ private class HeuristicDomBasedXssSink extends HeuristicSink, DomBasedXss::DomBa } } -private class HeuristicReflectedXssSink extends HeuristicSink, ReflectedXss::ReflectedXss::Sink { +private class HeuristicReflectedXssSink extends HeuristicSink, Xss::ReflectedXss::Sink { HeuristicReflectedXssSink() { isAssignedToOrConcatenatedWith(this, "(?i)(html|innerhtml)") or isArgTo(this, "(?i)(html|render)") or diff --git a/javascript/ql/test/library-tests/Security/CWE-338/InsecureRandomnessSource.ql b/javascript/ql/test/library-tests/Security/CWE-338/InsecureRandomnessSource.ql index 26c534c35ea..5eac9dd3632 100644 --- a/javascript/ql/test/library-tests/Security/CWE-338/InsecureRandomnessSource.ql +++ b/javascript/ql/test/library-tests/Security/CWE-338/InsecureRandomnessSource.ql @@ -1,5 +1,5 @@ import javascript -import semmle.javascript.security.dataflow.InsecureRandomness::InsecureRandomness +import semmle.javascript.security.dataflow.InsecureRandomnessQuery from Source s select s diff --git a/javascript/ql/test/library-tests/frameworks/Vue/tests.ql b/javascript/ql/test/library-tests/frameworks/Vue/tests.ql index a1f1f6586c7..858c1a89e4b 100644 --- a/javascript/ql/test/library-tests/frameworks/Vue/tests.ql +++ b/javascript/ql/test/library-tests/frameworks/Vue/tests.ql @@ -1,4 +1,5 @@ import javascript +import semmle.javascript.security.dataflow.Xss query predicate instance_getAPropertyValue(Vue::Instance i, string name, DataFlow::Node prop) { i.getAPropertyValue(name) = prop @@ -18,14 +19,10 @@ query predicate instance_heapStep( query predicate templateElement(Vue::Template::Element template) { any() } -import semmle.javascript.security.dataflow.DomBasedXss - query predicate vhtmlSourceWrite(Vue::VHtmlSourceWrite w, DataFlow::Node pred, DataFlow::Node succ) { w.step(pred, succ) } -import semmle.javascript.security.dataflow.DomBasedXss - query predicate xssSink(DomBasedXss::Sink s) { any() } query RemoteFlowSource remoteFlowSource() { any() } diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.ql b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.ql index b895391819a..d5230981801 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.ql +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.ql @@ -1,3 +1,3 @@ import javascript -import semmle.javascript.security.dataflow.TaintedPath::TaintedPath +import semmle.javascript.security.dataflow.TaintedPathQuery import testUtilities.ConsistencyChecking diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/ConsistencyDomBasedXss.ql b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/ConsistencyDomBasedXss.ql index 5144f45abc7..639a895263a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/ConsistencyDomBasedXss.ql +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/ConsistencyDomBasedXss.ql @@ -1,3 +1,3 @@ import javascript import testUtilities.ConsistencyChecking -import semmle.javascript.security.dataflow.DomBasedXss as DomXss +import semmle.javascript.security.dataflow.DomBasedXssQuery as DomXss diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.ql b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.ql index b532f0b8a75..9a27e9db4d4 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.ql +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.ql @@ -12,7 +12,7 @@ */ import javascript -import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss +import semmle.javascript.security.dataflow.DomBasedXssQuery import DataFlow::PathGraph import semmle.javascript.heuristics.AdditionalSources diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.ql b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.ql index 0d149053de3..4eff4921b12 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.ql +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.ql @@ -2,7 +2,7 @@ // Modern version of ReflectedXssWithCustomSanitizer_old.ql // import javascript -import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss +import semmle.javascript.security.dataflow.ReflectedXssQuery class IsVarNameSanitizer extends TaintTracking::AdditionalSanitizerGuardNode, DataFlow::CallNode { IsVarNameSanitizer() { getCalleeName() = "isVarName" } diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.ql b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.ql index b8c1503793a..2e5a95533f1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.ql +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.ql @@ -1,6 +1,6 @@ import javascript import semmle.javascript.heuristics.AdditionalSources -import semmle.javascript.security.dataflow.CodeInjection::CodeInjection +import semmle.javascript.security.dataflow.CodeInjectionQuery import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink 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 index f25d08771df..7a440ac58bb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql @@ -1,7 +1,7 @@ import javascript import testUtilities.ConsistencyChecking -import semmle.javascript.security.dataflow.PrototypePollutingAssignment +import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery -class Config extends ConsistencyConfiguration, PrototypePollutingAssignment::Configuration { +class Config extends ConsistencyConfiguration, Configuration { override File getAFile() { any() } } From 020d65befc5c7ccc20d42ad3e4ad7d74e06a2bd7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 11 Aug 2021 12:28:54 +0200 Subject: [PATCH 232/429] Fix StoredXssTypeTracking example query --- .../queries/dataflow/StoredXss/StoredXssTypeTracking.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql index 39704bdc215..c68541717f1 100644 --- a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql +++ b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXssTypeTracking.ql @@ -9,7 +9,6 @@ */ import javascript -import DataFlow import semmle.javascript.security.dataflow.StoredXssQuery import DataFlow::PathGraph @@ -18,7 +17,7 @@ import DataFlow::PathGraph */ DataFlow::SourceNode mysqlConnection(DataFlow::TypeTracker t) { t.start() and - result = moduleImport("mysql").getAMemberCall("createConnection") + result = DataFlow::moduleImport("mysql").getAMemberCall("createConnection") or exists(DataFlow::TypeTracker t2 | result = mysqlConnection(t2).track(t2, t)) } @@ -46,6 +45,6 @@ class MysqlSource extends Source { MysqlSource() { this = mysqlConnection().getAMethodCall("query").getCallback(1).getParameter(1) } } -from Configuration cfg, PathNode source, PathNode sink +from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value." From fd027451b1b918ebcfd8a50597543384ee550ec1 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 12 Aug 2021 09:14:12 +0200 Subject: [PATCH 233/429] JS: Fix StoresXss example query --- .../ql/examples/queries/dataflow/StoredXss/StoredXss.ql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql index 08d4abbcdd5..c18266451f8 100644 --- a/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql +++ b/javascript/ql/examples/queries/dataflow/StoredXss/StoredXss.ql @@ -8,7 +8,6 @@ */ import javascript -import DataFlow import semmle.javascript.security.dataflow.StoredXssQuery import DataFlow::PathGraph @@ -24,7 +23,7 @@ import DataFlow::PathGraph class MysqlSource extends Source { MysqlSource() { this = - moduleImport("mysql") + DataFlow::moduleImport("mysql") .getAMemberCall("createConnection") .getAMethodCall("query") .getCallback(1) @@ -32,6 +31,6 @@ class MysqlSource extends Source { } } -from Configuration cfg, PathNode source, PathNode sink +from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Stored XSS from $@.", source.getNode(), "database value." From a6c389698e5d877ed2af159e1437ff6378b8bcb6 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 12 Aug 2021 09:31:24 +0200 Subject: [PATCH 234/429] JS: Fix DomBasedXssQuery.qll --- .../semmle/javascript/security/dataflow/DomBasedXssQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll index a42d974c34b..46f6a136120 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll @@ -41,7 +41,7 @@ class HtmlInjectionConfiguration extends TaintTracking::Configuration { } override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) { - DomBasedXss::isOptionallySanitizedEdge(pred, succ) + isOptionallySanitizedEdge(pred, succ) } } From fe477ff98987f43f525adb0e26606c13ef964c17 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 12 Aug 2021 14:50:14 +0100 Subject: [PATCH 235/429] Fix more models based on review comments --- .../java/frameworks/apache/Collections.qll | 22 ++-- .../frameworks/apache-collections/Test.java | 116 +++++++++++------- 2 files changed, 86 insertions(+), 52 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index d0f631f4d2b..4f4a80dc37b 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -290,11 +290,15 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { ";CollectionUtils;true;predicatedCollection;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;removeAll;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;retainAll;;;Element of Argument[0];Element of ReturnValue;value", - ";CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value", - ";CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value", - ";CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value", - ";CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value", - ";CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;select;(Iterable,Predicate);;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;select;(Iterable,Predicate,Collection);;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;select;(Iterable,Predicate,Collection);;Argument[2];ReturnValue;value", + ";CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Element of Argument[0];Element of Argument[3];value", + ";CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Argument[2];ReturnValue;value", + ";CollectionUtils;true;selectRejected;(Iterable,Predicate);;Element of Argument[0];Element of ReturnValue;value", + ";CollectionUtils;true;selectRejected;(Iterable,Predicate,Collection);;Element of Argument[0];Element of Argument[2];value", + ";CollectionUtils;true;selectRejected;(Iterable,Predicate,Collection);;Argument[2];ReturnValue;value", ";CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", @@ -372,6 +376,7 @@ private class ApacheIteratorUtilsModel extends SummaryModelCsv { ";IteratorUtils;true;filteredListIterator;;;Element of Argument[0];Element of ReturnValue;value", ";IteratorUtils;true;find;;;Element of Argument[0];ReturnValue;value", ";IteratorUtils;true;first;;;Element of Argument[0];ReturnValue;value", + ";IteratorUtils;true;forEachButLast;;;Element of Argument[0];ReturnValue;value", ";IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value", ";IteratorUtils;true;getIterator;;;Element of Argument[0];Element of ReturnValue;value", ";IteratorUtils;true;getIterator;;;ArrayElement of Argument[0];Element of ReturnValue;value", @@ -432,6 +437,7 @@ private class ApacheIterableUtilsModel extends SummaryModelCsv { ";IterableUtils;true;filteredIterable;;;Element of Argument[0];Element of ReturnValue;value", ";IterableUtils;true;find;;;Element of Argument[0];ReturnValue;value", ";IterableUtils;true;first;;;Element of Argument[0];ReturnValue;value", + ";IterableUtils;true;forEachButLast;;;Element of Argument[0];ReturnValue;value", ";IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value", ";IterableUtils;true;loopingIterable;;;Element of Argument[0];Element of ReturnValue;value", ";IterableUtils;true;partition;;;Element of Argument[0];Element of Element of ReturnValue;value", @@ -475,9 +481,9 @@ private class ApacheMultiMapUtilsModel extends SummaryModelCsv { [ ";MultiMapUtils;true;emptyIfNull;;;Argument[0];ReturnValue;value", ";MultiMapUtils;true;getCollection;;;MapValue of Argument[0];ReturnValue;value", - ";MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value", - ";MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value", - ";MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value", + ";MultiMapUtils;true;getValuesAsBag;;;Element of MapValue of Argument[0];Element of ReturnValue;value", + ";MultiMapUtils;true;getValuesAsList;;;Element of MapValue of Argument[0];Element of ReturnValue;value", + ";MultiMapUtils;true;getValuesAsSet;;;Element of MapValue of Argument[0];Element of ReturnValue;value", ";MultiMapUtils;true;transformedMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", ";MultiMapUtils;true;transformedMultiValuedMap;;;MapValue of Argument[0];MapValue of ReturnValue;value", ";MultiMapUtils;true;unmodifiableMultiValuedMap;;;MapKey of Argument[0];MapKey of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index a88091f082e..bed2384a73f 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -1446,68 +1446,82 @@ public class Test { sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" - Collection out = null; - Iterable in = newVectorWithElement((String)source()); - CollectionUtils.select(in, null, out, null); - sink(getElement(out)); // $ hasValueFlow - } - { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[2];value" - Collection out = null; - Iterable in = newVectorWithElement((String)source()); - CollectionUtils.select(in, null, out); - sink(getElement(out)); // $ hasValueFlow - } - { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of Argument[3];value" - Collection out = null; - Iterable in = newVectorWithElement((String)source()); - CollectionUtils.select(in, null, null, out); - sink(getElement(out)); // $ hasValueFlow - } - { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" - Collection out = null; - Iterable in = newVectorWithElement((String)source()); - out = CollectionUtils.select(in, null, null, null); - sink(getElement(out)); // $ hasValueFlow - } - { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" - Collection out = null; - Iterable in = newVectorWithElement((String)source()); - out = CollectionUtils.select(in, null, null); - sink(getElement(out)); // $ hasValueFlow - } - { - // "org.apache.commons.collections4;CollectionUtils;true;select;;;Element of Argument[0];Element of ReturnValue;value" + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate);;Element of Argument[0];Element of ReturnValue;value" Collection out = null; Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.select(in, null); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of Argument[2];value" + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate,Collection);;Argument[2];ReturnValue;value" + Collection out = null; + Collection in = (Collection)source(); + out = CollectionUtils.select(null, null, in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate,Collection);;Element of Argument[0];Element of Argument[2];value" Collection out = null; Iterable in = newVectorWithElement((String)source()); - CollectionUtils.selectRejected(in, null, out); + CollectionUtils.select(in, null, out); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" + Collection mid = null; Collection out = null; Iterable in = newVectorWithElement((String)source()); - out = CollectionUtils.selectRejected(in, null, null); + out = CollectionUtils.select(in, null, mid); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;;;Element of Argument[0];Element of ReturnValue;value" + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Argument[2];ReturnValue;value" + Collection out = null; + Collection in = (Collection)source(); + out = CollectionUtils.select(null, null, in, null); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Element of Argument[0];Element of Argument[2];value" + Collection out = null; + Iterable in = newVectorWithElement((String)source()); + CollectionUtils.select(in, null, out, null); + sink(getElement(out)); // $ hasValueFlow + } + { + Collection mid = null; + Collection out = null; + Iterable in = newVectorWithElement((String)source()); + out = CollectionUtils.select(in, null, mid, null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;select;(Iterable,Predicate,Collection,Collection);;Element of Argument[0];Element of Argument[3];value" + Collection out = null; + Iterable in = newVectorWithElement((String)source()); + CollectionUtils.select(in, null, null, out); + sink(getElement(out)); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;(Iterable,Predicate);;Element of Argument[0];Element of ReturnValue;value" Collection out = null; Iterable in = newVectorWithElement((String)source()); out = CollectionUtils.selectRejected(in, null); sink(getElement(out)); // $ hasValueFlow } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;(Iterable,Predicate,Collection);;Argument[2];ReturnValue;value" + Collection out = null; + Collection in = (Collection)source(); + out = CollectionUtils.selectRejected(null, null, in); + sink(out); // $ hasValueFlow + } + { + // "org.apache.commons.collections4;CollectionUtils;true;selectRejected;(Iterable,Predicate,Collection);;Element of Argument[0];Element of Argument[2];value" + Collection out = null; + Iterable in = newVectorWithElement((String)source()); + CollectionUtils.selectRejected(in, null, out); + sink(getElement(out)); // $ hasValueFlow + } { // "org.apache.commons.collections4;CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value" Collection out = null; @@ -2088,6 +2102,13 @@ public class Test { out = IterableUtils.first(in); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IterableUtils;true;forEachButLast;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterable in = newVectorWithElement((String)source()); + out = IterableUtils.forEachButLast(in, null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;IterableUtils;true;get;;;Element of Argument[0];ReturnValue;value" Object out = null; @@ -2424,6 +2445,13 @@ public class Test { out = IteratorUtils.first(in); sink(out); // $ hasValueFlow } + { + // "org.apache.commons.collections4;IteratorUtils;true;forEachButLast;;;Element of Argument[0];ReturnValue;value" + Object out = null; + Iterator in = newListIteratorWithElement((String)source()); + out = IteratorUtils.forEachButLast(in, null); + sink(out); // $ hasValueFlow + } { // "org.apache.commons.collections4;IteratorUtils;true;get;;;Element of Argument[0];ReturnValue;value" Object out = null; @@ -2936,21 +2964,21 @@ public class Test { sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;MapValue of Argument[0];ReturnValue;value" + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsBag;;;Element of MapValue of Argument[0];Element of ReturnValue;value" Bag out = null; MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsBag(in, null); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;MapValue of Argument[0];ReturnValue;value" + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsList;;;Element of MapValue of Argument[0];Element of ReturnValue;value" List out = null; MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsList(in, null); sink(getElement(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;MapValue of Argument[0];ReturnValue;value" + // "org.apache.commons.collections4;MultiMapUtils;true;getValuesAsSet;;;Element of MapValue of Argument[0];Element of ReturnValue;value" Set out = null; MultiValuedMap in = newALVHMWithMapValue((String)source()); out = MultiMapUtils.getValuesAsSet(in, null); From 1c2476c6a15170dfd4707cec719db6fd9db1f4c9 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Thu, 12 Aug 2021 14:51:49 +0100 Subject: [PATCH 236/429] Add explanatory comments --- java/ql/src/semmle/code/java/frameworks/apache/Collections.qll | 3 +++ .../test/library-tests/frameworks/apache-collections/test.ql | 1 + 2 files changed, 4 insertions(+) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 4f4a80dc37b..92dfc534c56 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -301,6 +301,7 @@ private class ApacheCollectionUtilsModel extends SummaryModelCsv { ";CollectionUtils;true;selectRejected;(Iterable,Predicate,Collection);;Argument[2];ReturnValue;value", ";CollectionUtils;true;subtract;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;synchronizedCollection;;;Element of Argument[0];Element of ReturnValue;value", + // Note that `CollectionUtils.transformingCollection` does not transform existing list elements ";CollectionUtils;true;transformingCollection;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", ";CollectionUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", @@ -323,6 +324,7 @@ private class ApacheListUtilsModel extends SummaryModelCsv { ";ListUtils;true;fixedSizeList;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;intersection;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;intersection;;;Element of Argument[1];Element of ReturnValue;value", + // Note that `ListUtils.lazyList` does not transform existing list elements ";ListUtils;true;lazyList;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[0];ReturnValue;taint", ";ListUtils;true;longestCommonSubsequence;(CharSequence,CharSequence);;Argument[1];ReturnValue;taint", @@ -340,6 +342,7 @@ private class ApacheListUtilsModel extends SummaryModelCsv { ";ListUtils;true;sum;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;sum;;;Element of Argument[1];Element of ReturnValue;value", ";ListUtils;true;synchronizedList;;;Element of Argument[0];Element of ReturnValue;value", + // Note that `ListUtils.transformedList` does not transform existing list elements ";ListUtils;true;transformedList;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;union;;;Element of Argument[0];Element of ReturnValue;value", ";ListUtils;true;union;;;Element of Argument[1];Element of ReturnValue;value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/test.ql b/java/ql/test/library-tests/frameworks/apache-collections/test.ql index 74a65d5922e..766606c0ba1 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/test.ql +++ b/java/ql/test/library-tests/frameworks/apache-collections/test.ql @@ -9,6 +9,7 @@ class SummaryModelTest extends SummaryModelCsv { row = [ //"package;type;overrides;name;signature;ext;inputspec;outputspec;kind", + // This is temporarily modelled for the helper function newEnumerationWithElement, until the relevant package is modelled "org.apache.commons.collections4.iterators;IteratorEnumeration;true;IteratorEnumeration;;;Element of Argument[0];Element of Argument[-1];value", "generatedtest;Test;false;newRBWithMapValue;;;Argument[0];MapValue of ReturnValue;value", "generatedtest;Test;false;newRBWithMapKey;;;Argument[0];MapKey of ReturnValue;value" From 25649a61c4b83bc8430519da56480bee9611d8d4 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Tue, 25 May 2021 12:15:23 -0700 Subject: [PATCH 237/429] Java: Add models for the Spring `web.util` package --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../code/java/frameworks/spring/Spring.qll | 1 + .../java/frameworks/spring/SpringWebUtil.qll | 210 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll diff --git a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll index aae71ce6d9a..748e5a12c5a 100644 --- a/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll @@ -95,6 +95,7 @@ private module Frameworks { private import semmle.code.java.frameworks.spring.SpringWebClient private import semmle.code.java.frameworks.spring.SpringBeans private import semmle.code.java.frameworks.spring.SpringWebMultipart + private import semmle.code.java.frameworks.spring.SpringWebUtil private import semmle.code.java.security.ResponseSplitting private import semmle.code.java.security.InformationLeak private import semmle.code.java.security.GroovyInjection diff --git a/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll b/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll index 21794a9d92c..10bf4e677f8 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/Spring.qll @@ -39,6 +39,7 @@ import semmle.code.java.frameworks.spring.SpringUtil import semmle.code.java.frameworks.spring.SpringValidation import semmle.code.java.frameworks.spring.SpringValue import semmle.code.java.frameworks.spring.SpringWebMultipart +import semmle.code.java.frameworks.spring.SpringWebUtil import semmle.code.java.frameworks.spring.SpringXMLElement import semmle.code.java.frameworks.spring.metrics.MetricSpringBean import semmle.code.java.frameworks.spring.metrics.MetricSpringBeanFile diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll new file mode 100644 index 00000000000..667d6723203 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll @@ -0,0 +1,210 @@ +/** Provides models of taint flow in `org.springframework.web.util` */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class FlowSummaries extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;host;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;host;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;path;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;pathSegment;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;port;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;query;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];SyntheticField[uri.Query] ofArgument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriBuilderFactory;true;builder;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[-1..0];ReturnValue;taint", + "org.springframework.web.util;UriComponents$UriTemplateVariables;true;getValue;;;MapValue of Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint", + "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint", + "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.springframework.web.util;AbstractUriTemplateHandler;true;getBaseUrl;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;AbstractUriTemplateHandler;true;setBaseUrl;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;AbstractUriTemplateHandler;true;setDefaultUriVariables;;;Argument[0];Argument[-1];taint", + // writing to a `Request` or `Response` currently doesn't propagate taint to the object itself. + "org.springframework.web.util;ContentCachingRequestWrapper;false;ContentCachingRequestWrapper;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;ContentCachingRequestWrapper;false;getContentAsByteArray;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;ContentCachingResponseWrapper;false;ContentCachingResponseWrapper;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentAsByteArray;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentInputStream;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;builder;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;getDefaultUriVariables;;;Argument[-1];MapValue of ReturnValue;taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;setDefaultUriVariables;;;MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;DefaultUriBuilderFactory;false;uriString;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;HtmlUtils;false;htmlEscape;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;HtmlUtils;false;htmlEscapeDecimal;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;HtmlUtils;false;htmlEscapeHex;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;HtmlUtils;false;htmlUnescape;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint", + "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPathValue;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;ServletRequestPathUtils;false;getParsedRequestPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;ServletRequestPathUtils;false;parseAndCache;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;ServletRequestPathUtils;false;setParsedRequestPath;;;Argument[0];Argument[1];taint", + "org.springframework.web.util;UriComponents;false;UriComponents;;;Argument[0..1];Argument[-1];taint", + "org.springframework.web.util;UriComponents;false;copyToUriComponentsBuilder;;;Argument[-1];Argument[0];taint", + "org.springframework.web.util;UriComponents;false;encode;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;expand;(UriTemplateVariables);;MapValue of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getFragment;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getHost;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getPath;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getPathSegments;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getQuery;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[-1];MapKey of ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[-1];Element of MapValue of ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getScheme;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getSchemeSpecificPart;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;getUserInfo;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;toUri;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponents;false;toUriString;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;build;(Map);;MapValue of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;build;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Map);;MapValue of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;cloneBuilder;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromHttpRequest;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromHttpUrl;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromOriginHeader;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromUri;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;fromUriString;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;ArrayElement of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;port;(String);;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;MapKey of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;MapKey of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;toUriString;;;Argument[-1];ReturnValue;taint", + "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;MapValue of Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[0];Argument[-1];taint", + "org.springframework.web.util;UriTemplate;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriTemplate;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriTemplate;false;getVariableNames;;;Argument[-1];Element of ReturnValue;taint", + "org.springframework.web.util;UriTemplate;false;match;;;Argument[0];MapValue of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;decode;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encode;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeAuthority;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeFragment;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeHost;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodePath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodePathSegment;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodePort;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeQuery;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeQueryParam;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapKey of Argument[0];MapKey of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapValue of Argument[0];MapValue of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeScheme;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapValue of Argument[0];MapValue of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapKey of Argument[0];MapKey of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Object[]);;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;encodeUserInfo;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UriUtils;false;extractFileExtension;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value", + "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value", + "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;decodeRequestString;;;Argument[1];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getContextPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getOriginatingContextPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getOriginatingQueryString;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getOriginatingRequestUri;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getOriginatingServletPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getRequestUri;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getResolvedLookupPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;getServletPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;removeSemicolonContent;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;UrlPathHelper;false;resolveAndCacheLookupPath;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;findParameterValue;(Map,String);;MapValue of Argument[0];ReturnValue;value", + "org.springframework.web.util;WebUtils;false;findParameterValue;(ServletRequest,String);;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getCookie;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getNativeRequest;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getNativeResponse;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapKey of ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapValue of ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getRealPath;;;Argument[0..1];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getRequiredSessionAttribute;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;getSessionAttribute;;;Argument[0];ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapKey of ReturnValue;taint", + "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapValue of ReturnValue;taint" + ] + } +} From fd0ea15719d6f923692fca7c9c16d20350777272 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 14 Jul 2021 04:24:35 -0700 Subject: [PATCH 238/429] Add stubs for Spring web.util tests --- .../javax/servlet/AsyncContext.java | 31 ++++++++ .../javax/servlet/AsyncEvent.java | 20 +++++ .../javax/servlet/AsyncListener.java | 14 ++++ .../javax/servlet/DispatcherType.java | 10 +++ .../javax/servlet/Filter.java | 15 ++++ .../javax/servlet/FilterChain.java | 11 +++ .../javax/servlet/FilterConfig.java | 14 ++++ .../javax/servlet/FilterRegistration.java | 19 +++++ .../javax/servlet/HttpConstraintElement.java | 16 ++++ .../servlet/HttpMethodConstraintElement.java | 13 ++++ .../javax/servlet/MultipartConfigElement.java | 17 ++++ .../javax/servlet/ReadListener.java | 12 +++ .../javax/servlet/Registration.java | 20 +++++ .../javax/servlet/RequestDispatcher.java | 18 +++++ .../javax/servlet/ServletConfig.java | 2 +- .../javax/servlet/ServletContext.java | 54 +++++++++++-- .../javax/servlet/ServletInputStream.java | 4 + .../javax/servlet/ServletOutputStream.java | 3 + .../javax/servlet/ServletRegistration.java | 23 ++++++ .../javax/servlet/ServletRequest.java | 20 ++++- .../javax/servlet/ServletRequestWrapper.java | 62 +++++++++++++++ .../javax/servlet/ServletResponse.java | 1 + .../javax/servlet/ServletResponseWrapper.java | 34 ++++++++ .../javax/servlet/ServletSecurityElement.java | 19 +++++ .../javax/servlet/SessionCookieConfig.java | 22 ++++++ .../javax/servlet/SessionTrackingMode.java | 10 +++ .../javax/servlet/WriteListener.java | 11 +++ .../servlet/annotation/HttpConstraint.java | 13 ++++ .../servlet/annotation/MultipartConfig.java | 13 ++++ .../servlet/annotation/ServletSecurity.java | 21 +++++ .../descriptor/JspConfigDescriptor.java | 13 ++++ .../JspPropertyGroupDescriptor.java | 21 +++++ .../servlet/descriptor/TaglibDescriptor.java | 10 +++ .../javax/servlet/http/Cookie.java | 5 +- .../servlet/http/HttpServletMapping.java | 13 ++++ .../servlet/http/HttpServletRequest.java | 20 ++++- .../http/HttpServletRequestWrapper.java | 57 ++++++++++++++ .../servlet/http/HttpServletResponse.java | 77 +++++++++++++++++++ .../http/HttpServletResponseWrapper.java | 39 ++++++++++ .../javax/servlet/http/HttpSession.java | 2 +- .../servlet/http/HttpSessionContext.java | 2 +- .../javax/servlet/http/MappingMatch.java | 10 +++ .../javax/servlet/http/Part.java | 20 +++++ .../javax/servlet/http/PushBuilder.java | 23 ++++++ .../org/springframework/http/HttpMessage.java | 10 +++ .../org/springframework/http/HttpRequest.java | 14 ++++ .../http/server/PathContainer.java | 28 +++++++ .../http/server/RequestPath.java | 15 ++++ .../web/util/AbstractUriTemplateHandler.java | 20 +++++ .../util/ContentCachingRequestWrapper.java | 26 +++++++ .../util/ContentCachingResponseWrapper.java | 32 ++++++++ .../web/util/CookieGenerator.java | 29 +++++++ .../web/util/DefaultUriBuilderFactory.java | 31 ++++++++ .../springframework/web/util/HtmlUtils.java | 16 ++++ .../web/util/ServletContextPropertyUtils.java | 12 +++ .../web/util/ServletRequestPathUtils.java | 21 +++++ .../springframework/web/util/UriBuilder.java | 33 ++++++++ .../web/util/UriBuilderFactory.java | 12 +++ .../web/util/UriComponents.java | 46 +++++++++++ .../web/util/UriComponentsBuilder.java | 63 +++++++++++++++ .../springframework/web/util/UriTemplate.java | 20 +++++ .../web/util/UriTemplateHandler.java | 12 +++ .../springframework/web/util/UriUtils.java | 40 ++++++++++ .../web/util/UrlPathHelper.java | 44 +++++++++++ .../springframework/web/util/WebUtils.java | 69 +++++++++++++++++ 65 files changed, 1432 insertions(+), 15 deletions(-) create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncContext.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncEvent.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncListener.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/DispatcherType.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Filter.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterChain.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterConfig.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterRegistration.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpConstraintElement.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpMethodConstraintElement.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/MultipartConfigElement.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ReadListener.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Registration.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRegistration.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequestWrapper.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponseWrapper.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletSecurityElement.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionCookieConfig.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionTrackingMode.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/WriteListener.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/HttpConstraint.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/MultipartConfig.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/ServletSecurity.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspConfigDescriptor.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspPropertyGroupDescriptor.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/TaglibDescriptor.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletMapping.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequestWrapper.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponse.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponseWrapper.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/MappingMatch.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Part.java create mode 100644 java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/PushBuilder.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpMessage.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpRequest.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/PathContainer.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/RequestPath.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/AbstractUriTemplateHandler.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingRequestWrapper.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingResponseWrapper.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/CookieGenerator.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/DefaultUriBuilderFactory.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/HtmlUtils.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletContextPropertyUtils.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletRequestPathUtils.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilder.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilderFactory.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponents.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponentsBuilder.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplate.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplateHandler.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriUtils.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UrlPathHelper.java create mode 100644 java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/WebUtils.java diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncContext.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncContext.java new file mode 100644 index 00000000000..1f50fb06303 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncContext.java @@ -0,0 +1,31 @@ +// Generated automatically from javax.servlet.AsyncContext for testing purposes + +package javax.servlet; + +import javax.servlet.AsyncListener; +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public interface AsyncContext +{ + T createListener(Class p0); + ServletRequest getRequest(); + ServletResponse getResponse(); + boolean hasOriginalRequestAndResponse(); + long getTimeout(); + static String ASYNC_CONTEXT_PATH = null; + static String ASYNC_MAPPING = null; + static String ASYNC_PATH_INFO = null; + static String ASYNC_QUERY_STRING = null; + static String ASYNC_REQUEST_URI = null; + static String ASYNC_SERVLET_PATH = null; + void addListener(AsyncListener p0); + void addListener(AsyncListener p0, ServletRequest p1, ServletResponse p2); + void complete(); + void dispatch(); + void dispatch(ServletContext p0, String p1); + void dispatch(String p0); + void setTimeout(long p0); + void start(Runnable p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncEvent.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncEvent.java new file mode 100644 index 00000000000..d7cb9c2b175 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncEvent.java @@ -0,0 +1,20 @@ +// Generated automatically from javax.servlet.AsyncEvent for testing purposes + +package javax.servlet; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public class AsyncEvent +{ + protected AsyncEvent() {} + public AsyncContext getAsyncContext(){ return null; } + public AsyncEvent(AsyncContext p0){} + public AsyncEvent(AsyncContext p0, ServletRequest p1, ServletResponse p2){} + public AsyncEvent(AsyncContext p0, ServletRequest p1, ServletResponse p2, Throwable p3){} + public AsyncEvent(AsyncContext p0, Throwable p1){} + public ServletRequest getSuppliedRequest(){ return null; } + public ServletResponse getSuppliedResponse(){ return null; } + public Throwable getThrowable(){ return null; } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncListener.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncListener.java new file mode 100644 index 00000000000..2723482f668 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/AsyncListener.java @@ -0,0 +1,14 @@ +// Generated automatically from javax.servlet.AsyncListener for testing purposes + +package javax.servlet; + +import java.util.EventListener; +import javax.servlet.AsyncEvent; + +public interface AsyncListener extends EventListener +{ + void onComplete(AsyncEvent p0); + void onError(AsyncEvent p0); + void onStartAsync(AsyncEvent p0); + void onTimeout(AsyncEvent p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/DispatcherType.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/DispatcherType.java new file mode 100644 index 00000000000..2b7b44f328d --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/DispatcherType.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.servlet.DispatcherType for testing purposes + +package javax.servlet; + + +public enum DispatcherType +{ + ASYNC, ERROR, FORWARD, INCLUDE, REQUEST; + private DispatcherType() {} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Filter.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Filter.java new file mode 100644 index 00000000000..64b9f9d73a8 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Filter.java @@ -0,0 +1,15 @@ +// Generated automatically from javax.servlet.Filter for testing purposes + +package javax.servlet; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public interface Filter +{ + default void destroy(){} + default void init(FilterConfig p0){} + void doFilter(ServletRequest p0, ServletResponse p1, FilterChain p2); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterChain.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterChain.java new file mode 100644 index 00000000000..f64ab722684 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterChain.java @@ -0,0 +1,11 @@ +// Generated automatically from javax.servlet.FilterChain for testing purposes + +package javax.servlet; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public interface FilterChain +{ + void doFilter(ServletRequest p0, ServletResponse p1); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterConfig.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterConfig.java new file mode 100644 index 00000000000..0e140c6680c --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterConfig.java @@ -0,0 +1,14 @@ +// Generated automatically from javax.servlet.FilterConfig for testing purposes + +package javax.servlet; + +import java.util.Enumeration; +import javax.servlet.ServletContext; + +public interface FilterConfig +{ + Enumeration getInitParameterNames(); + ServletContext getServletContext(); + String getFilterName(); + String getInitParameter(String p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterRegistration.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterRegistration.java new file mode 100644 index 00000000000..6ad0739ceb6 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/FilterRegistration.java @@ -0,0 +1,19 @@ +// Generated automatically from javax.servlet.FilterRegistration for testing purposes + +package javax.servlet; + +import java.util.Collection; +import java.util.EnumSet; +import javax.servlet.DispatcherType; +import javax.servlet.Registration; + +public interface FilterRegistration extends Registration +{ + Collection getServletNameMappings(); + Collection getUrlPatternMappings(); + static public interface Dynamic extends FilterRegistration, Registration.Dynamic + { + } + void addMappingForServletNames(EnumSet p0, boolean p1, String... p2); + void addMappingForUrlPatterns(EnumSet p0, boolean p1, String... p2); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpConstraintElement.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpConstraintElement.java new file mode 100644 index 00000000000..6598aa47cc5 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpConstraintElement.java @@ -0,0 +1,16 @@ +// Generated automatically from javax.servlet.HttpConstraintElement for testing purposes + +package javax.servlet; + +import javax.servlet.annotation.ServletSecurity; + +public class HttpConstraintElement +{ + public HttpConstraintElement(){} + public HttpConstraintElement(ServletSecurity.EmptyRoleSemantic p0){} + public HttpConstraintElement(ServletSecurity.EmptyRoleSemantic p0, ServletSecurity.TransportGuarantee p1, String... p2){} + public HttpConstraintElement(ServletSecurity.TransportGuarantee p0, String... p1){} + public ServletSecurity.EmptyRoleSemantic getEmptyRoleSemantic(){ return null; } + public ServletSecurity.TransportGuarantee getTransportGuarantee(){ return null; } + public String[] getRolesAllowed(){ return null; } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpMethodConstraintElement.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpMethodConstraintElement.java new file mode 100644 index 00000000000..ddb52527004 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/HttpMethodConstraintElement.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.servlet.HttpMethodConstraintElement for testing purposes + +package javax.servlet; + +import javax.servlet.HttpConstraintElement; + +public class HttpMethodConstraintElement extends HttpConstraintElement +{ + protected HttpMethodConstraintElement() {} + public HttpMethodConstraintElement(String p0){} + public HttpMethodConstraintElement(String p0, HttpConstraintElement p1){} + public String getMethodName(){ return null; } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/MultipartConfigElement.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/MultipartConfigElement.java new file mode 100644 index 00000000000..8470d9a5317 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/MultipartConfigElement.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.servlet.MultipartConfigElement for testing purposes + +package javax.servlet; + +import javax.servlet.annotation.MultipartConfig; + +public class MultipartConfigElement +{ + protected MultipartConfigElement() {} + public MultipartConfigElement(MultipartConfig p0){} + public MultipartConfigElement(String p0){} + public MultipartConfigElement(String p0, long p1, long p2, int p3){} + public String getLocation(){ return null; } + public int getFileSizeThreshold(){ return 0; } + public long getMaxFileSize(){ return 0; } + public long getMaxRequestSize(){ return 0; } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ReadListener.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ReadListener.java new file mode 100644 index 00000000000..367594ef7da --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ReadListener.java @@ -0,0 +1,12 @@ +// Generated automatically from javax.servlet.ReadListener for testing purposes + +package javax.servlet; + +import java.util.EventListener; + +public interface ReadListener extends EventListener +{ + void onAllDataRead(); + void onDataAvailable(); + void onError(Throwable p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Registration.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Registration.java new file mode 100644 index 00000000000..5d4095813ef --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/Registration.java @@ -0,0 +1,20 @@ +// Generated automatically from javax.servlet.Registration for testing purposes + +package javax.servlet; + +import java.util.Map; +import java.util.Set; + +public interface Registration +{ + Map getInitParameters(); + Set setInitParameters(Map p0); + String getClassName(); + String getInitParameter(String p0); + String getName(); + boolean setInitParameter(String p0, String p1); + static public interface Dynamic extends Registration + { + void setAsyncSupported(boolean p0); + } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/RequestDispatcher.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/RequestDispatcher.java index 287dc4452a8..ad017e4f501 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/RequestDispatcher.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/RequestDispatcher.java @@ -7,6 +7,24 @@ import javax.servlet.ServletResponse; public interface RequestDispatcher { + static String ERROR_EXCEPTION = null; + static String ERROR_EXCEPTION_TYPE = null; + static String ERROR_MESSAGE = null; + static String ERROR_REQUEST_URI = null; + static String ERROR_SERVLET_NAME = null; + static String ERROR_STATUS_CODE = null; + static String FORWARD_CONTEXT_PATH = null; + static String FORWARD_MAPPING = null; + static String FORWARD_PATH_INFO = null; + static String FORWARD_QUERY_STRING = null; + static String FORWARD_REQUEST_URI = null; + static String FORWARD_SERVLET_PATH = null; + static String INCLUDE_CONTEXT_PATH = null; + static String INCLUDE_MAPPING = null; + static String INCLUDE_PATH_INFO = null; + static String INCLUDE_QUERY_STRING = null; + static String INCLUDE_REQUEST_URI = null; + static String INCLUDE_SERVLET_PATH = null; void forward(ServletRequest p0, ServletResponse p1); void include(ServletRequest p0, ServletResponse p1); } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletConfig.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletConfig.java index 09d75acb268..c483c16ac4e 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletConfig.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletConfig.java @@ -7,7 +7,7 @@ import javax.servlet.ServletContext; public interface ServletConfig { - Enumeration getInitParameterNames(); + Enumeration getInitParameterNames(); ServletContext getServletContext(); String getInitParameter(String p0); String getServletName(); diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletContext.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletContext.java index c9c3cc1112f..5ce42a40282 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletContext.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletContext.java @@ -5,35 +5,79 @@ package javax.servlet; import java.io.InputStream; import java.net.URL; import java.util.Enumeration; +import java.util.EventListener; +import java.util.Map; import java.util.Set; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; +import javax.servlet.ServletRegistration; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; public interface ServletContext { - Enumeration getAttributeNames(); - Enumeration getInitParameterNames(); - Enumeration getServletNames(); - Enumeration getServlets(); + T createListener(Class p0); + void addListener(T p0); + T createFilter(Class p0); + T createServlet(Class p0); + ClassLoader getClassLoader(); + Enumeration getServlets(); + Enumeration getAttributeNames(); + Enumeration getInitParameterNames(); + Enumeration getServletNames(); + FilterRegistration getFilterRegistration(String p0); + FilterRegistration.Dynamic addFilter(String p0, Class p1); + FilterRegistration.Dynamic addFilter(String p0, Filter p1); + FilterRegistration.Dynamic addFilter(String p0, String p1); InputStream getResourceAsStream(String p0); + JspConfigDescriptor getJspConfigDescriptor(); + Map getFilterRegistrations(); + Map getServletRegistrations(); Object getAttribute(String p0); RequestDispatcher getNamedDispatcher(String p0); RequestDispatcher getRequestDispatcher(String p0); Servlet getServlet(String p0); ServletContext getContext(String p0); - Set getResourcePaths(String p0); + ServletRegistration getServletRegistration(String p0); + ServletRegistration.Dynamic addJspFile(String p0, String p1); + ServletRegistration.Dynamic addServlet(String p0, Class p1); + ServletRegistration.Dynamic addServlet(String p0, Servlet p1); + ServletRegistration.Dynamic addServlet(String p0, String p1); + SessionCookieConfig getSessionCookieConfig(); + Set getDefaultSessionTrackingModes(); + Set getEffectiveSessionTrackingModes(); + Set getResourcePaths(String p0); String getContextPath(); String getInitParameter(String p0); String getMimeType(String p0); String getRealPath(String p0); + String getRequestCharacterEncoding(); + String getResponseCharacterEncoding(); String getServerInfo(); String getServletContextName(); + String getVirtualServerName(); URL getResource(String p0); + boolean setInitParameter(String p0, String p1); + int getEffectiveMajorVersion(); + int getEffectiveMinorVersion(); int getMajorVersion(); int getMinorVersion(); + int getSessionTimeout(); + static String ORDERED_LIBS = null; + static String TEMPDIR = null; + void addListener(Class p0); + void addListener(String p0); + void declareRoles(String... p0); void log(Exception p0, String p1); void log(String p0); void log(String p0, Throwable p1); void removeAttribute(String p0); void setAttribute(String p0, Object p1); + void setRequestCharacterEncoding(String p0); + void setResponseCharacterEncoding(String p0); + void setSessionTimeout(int p0); + void setSessionTrackingModes(Set p0); } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletInputStream.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletInputStream.java index ddaf28ba36a..31034066970 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletInputStream.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletInputStream.java @@ -3,9 +3,13 @@ package javax.servlet; import java.io.InputStream; +import javax.servlet.ReadListener; abstract public class ServletInputStream extends InputStream { protected ServletInputStream(){} + public abstract boolean isFinished(); + public abstract boolean isReady(); + public abstract void setReadListener(ReadListener p0); public int readLine(byte[] p0, int p1, int p2){ return 0; } } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletOutputStream.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletOutputStream.java index 18f93cc0ec3..52a2162c9eb 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletOutputStream.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletOutputStream.java @@ -3,10 +3,13 @@ package javax.servlet; import java.io.OutputStream; +import javax.servlet.WriteListener; abstract public class ServletOutputStream extends OutputStream { protected ServletOutputStream(){} + public abstract boolean isReady(); + public abstract void setWriteListener(WriteListener p0); public void print(String p0){} public void print(boolean p0){} public void print(char p0){} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRegistration.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRegistration.java new file mode 100644 index 00000000000..a1cc66f2d19 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRegistration.java @@ -0,0 +1,23 @@ +// Generated automatically from javax.servlet.ServletRegistration for testing purposes + +package javax.servlet; + +import java.util.Collection; +import java.util.Set; +import javax.servlet.MultipartConfigElement; +import javax.servlet.Registration; +import javax.servlet.ServletSecurityElement; + +public interface ServletRegistration extends Registration +{ + Collection getMappings(); + Set addMapping(String... p0); + String getRunAsRole(); + static public interface Dynamic extends Registration.Dynamic, ServletRegistration + { + Set setServletSecurity(ServletSecurityElement p0); + void setLoadOnStartup(int p0); + void setMultipartConfig(MultipartConfigElement p0); + void setRunAsRole(String p0); + } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequest.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequest.java index d4f4343b70c..fc0db462cc0 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequest.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequest.java @@ -6,19 +6,28 @@ import java.io.BufferedReader; import java.util.Enumeration; import java.util.Locale; import java.util.Map; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; public interface ServletRequest { + AsyncContext getAsyncContext(); + AsyncContext startAsync(); + AsyncContext startAsync(ServletRequest p0, ServletResponse p1); BufferedReader getReader(); - Enumeration getAttributeNames(); - Enumeration getLocales(); - Enumeration getParameterNames(); + DispatcherType getDispatcherType(); + Enumeration getLocales(); + Enumeration getAttributeNames(); + Enumeration getParameterNames(); Locale getLocale(); - Map getParameterMap(); + Map getParameterMap(); Object getAttribute(String p0); RequestDispatcher getRequestDispatcher(String p0); + ServletContext getServletContext(); ServletInputStream getInputStream(); String getCharacterEncoding(); String getContentType(); @@ -32,11 +41,14 @@ public interface ServletRequest String getScheme(); String getServerName(); String[] getParameterValues(String p0); + boolean isAsyncStarted(); + boolean isAsyncSupported(); boolean isSecure(); int getContentLength(); int getLocalPort(); int getRemotePort(); int getServerPort(); + long getContentLengthLong(); void removeAttribute(String p0); void setAttribute(String p0, Object p1); void setCharacterEncoding(String p0); diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequestWrapper.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequestWrapper.java new file mode 100644 index 00000000000..df7c719c44a --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletRequestWrapper.java @@ -0,0 +1,62 @@ +// Generated automatically from javax.servlet.ServletRequestWrapper for testing purposes + +package javax.servlet; + +import java.io.BufferedReader; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public class ServletRequestWrapper implements ServletRequest +{ + protected ServletRequestWrapper() {} + public AsyncContext getAsyncContext(){ return null; } + public AsyncContext startAsync(){ return null; } + public AsyncContext startAsync(ServletRequest p0, ServletResponse p1){ return null; } + public BufferedReader getReader(){ return null; } + public DispatcherType getDispatcherType(){ return null; } + public Enumeration getLocales(){ return null; } + public Enumeration getAttributeNames(){ return null; } + public Enumeration getParameterNames(){ return null; } + public Locale getLocale(){ return null; } + public Map getParameterMap(){ return null; } + public Object getAttribute(String p0){ return null; } + public RequestDispatcher getRequestDispatcher(String p0){ return null; } + public ServletContext getServletContext(){ return null; } + public ServletInputStream getInputStream(){ return null; } + public ServletRequest getRequest(){ return null; } + public ServletRequestWrapper(ServletRequest p0){} + public String getCharacterEncoding(){ return null; } + public String getContentType(){ return null; } + public String getLocalAddr(){ return null; } + public String getLocalName(){ return null; } + public String getParameter(String p0){ return null; } + public String getProtocol(){ return null; } + public String getRealPath(String p0){ return null; } + public String getRemoteAddr(){ return null; } + public String getRemoteHost(){ return null; } + public String getScheme(){ return null; } + public String getServerName(){ return null; } + public String[] getParameterValues(String p0){ return null; } + public boolean isAsyncStarted(){ return false; } + public boolean isAsyncSupported(){ return false; } + public boolean isSecure(){ return false; } + public boolean isWrapperFor(Class p0){ return false; } + public boolean isWrapperFor(ServletRequest p0){ return false; } + public int getContentLength(){ return 0; } + public int getLocalPort(){ return 0; } + public int getRemotePort(){ return 0; } + public int getServerPort(){ return 0; } + public long getContentLengthLong(){ return 0; } + public void removeAttribute(String p0){} + public void setAttribute(String p0, Object p1){} + public void setCharacterEncoding(String p0){} + public void setRequest(ServletRequest p0){} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponse.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponse.java index 38659f14516..db6610bc15d 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponse.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponse.java @@ -21,6 +21,7 @@ public interface ServletResponse void setBufferSize(int p0); void setCharacterEncoding(String p0); void setContentLength(int p0); + void setContentLengthLong(long p0); void setContentType(String p0); void setLocale(Locale p0); } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponseWrapper.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponseWrapper.java new file mode 100644 index 00000000000..c8105f36ce9 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletResponseWrapper.java @@ -0,0 +1,34 @@ +// Generated automatically from javax.servlet.ServletResponseWrapper for testing purposes + +package javax.servlet; + +import java.io.PrintWriter; +import java.util.Locale; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletResponse; + +public class ServletResponseWrapper implements ServletResponse +{ + protected ServletResponseWrapper() {} + public Locale getLocale(){ return null; } + public PrintWriter getWriter(){ return null; } + public ServletOutputStream getOutputStream(){ return null; } + public ServletResponse getResponse(){ return null; } + public ServletResponseWrapper(ServletResponse p0){} + public String getCharacterEncoding(){ return null; } + public String getContentType(){ return null; } + public boolean isCommitted(){ return false; } + public boolean isWrapperFor(Class p0){ return false; } + public boolean isWrapperFor(ServletResponse p0){ return false; } + public int getBufferSize(){ return 0; } + public void flushBuffer(){} + public void reset(){} + public void resetBuffer(){} + public void setBufferSize(int p0){} + public void setCharacterEncoding(String p0){} + public void setContentLength(int p0){} + public void setContentLengthLong(long p0){} + public void setContentType(String p0){} + public void setLocale(Locale p0){} + public void setResponse(ServletResponse p0){} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletSecurityElement.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletSecurityElement.java new file mode 100644 index 00000000000..def47937391 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/ServletSecurityElement.java @@ -0,0 +1,19 @@ +// Generated automatically from javax.servlet.ServletSecurityElement for testing purposes + +package javax.servlet; + +import java.util.Collection; +import javax.servlet.HttpConstraintElement; +import javax.servlet.HttpMethodConstraintElement; +import javax.servlet.annotation.ServletSecurity; + +public class ServletSecurityElement extends HttpConstraintElement +{ + public Collection getHttpMethodConstraints(){ return null; } + public Collection getMethodNames(){ return null; } + public ServletSecurityElement(){} + public ServletSecurityElement(Collection p0){} + public ServletSecurityElement(HttpConstraintElement p0){} + public ServletSecurityElement(HttpConstraintElement p0, Collection p1){} + public ServletSecurityElement(ServletSecurity p0){} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionCookieConfig.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionCookieConfig.java new file mode 100644 index 00000000000..4cae9a11f30 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionCookieConfig.java @@ -0,0 +1,22 @@ +// Generated automatically from javax.servlet.SessionCookieConfig for testing purposes + +package javax.servlet; + + +public interface SessionCookieConfig +{ + String getComment(); + String getDomain(); + String getName(); + String getPath(); + boolean isHttpOnly(); + boolean isSecure(); + int getMaxAge(); + void setComment(String p0); + void setDomain(String p0); + void setHttpOnly(boolean p0); + void setMaxAge(int p0); + void setName(String p0); + void setPath(String p0); + void setSecure(boolean p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionTrackingMode.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionTrackingMode.java new file mode 100644 index 00000000000..684ac40c56f --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/SessionTrackingMode.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.servlet.SessionTrackingMode for testing purposes + +package javax.servlet; + + +public enum SessionTrackingMode +{ + COOKIE, SSL, URL; + private SessionTrackingMode() {} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/WriteListener.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/WriteListener.java new file mode 100644 index 00000000000..24fe504271c --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/WriteListener.java @@ -0,0 +1,11 @@ +// Generated automatically from javax.servlet.WriteListener for testing purposes + +package javax.servlet; + +import java.util.EventListener; + +public interface WriteListener extends EventListener +{ + void onError(Throwable p0); + void onWritePossible(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/HttpConstraint.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/HttpConstraint.java new file mode 100644 index 00000000000..ef2a244342c --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/HttpConstraint.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.servlet.annotation.HttpConstraint for testing purposes + +package javax.servlet.annotation; + +import java.lang.annotation.Annotation; +import javax.servlet.annotation.ServletSecurity; + +public interface HttpConstraint extends Annotation +{ + ServletSecurity.EmptyRoleSemantic value(); + ServletSecurity.TransportGuarantee transportGuarantee(); + String[] rolesAllowed(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/MultipartConfig.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/MultipartConfig.java new file mode 100644 index 00000000000..6b41173f6fa --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/MultipartConfig.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.servlet.annotation.MultipartConfig for testing purposes + +package javax.servlet.annotation; + +import java.lang.annotation.Annotation; + +public interface MultipartConfig extends Annotation +{ + String location(); + int fileSizeThreshold(); + long maxFileSize(); + long maxRequestSize(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/ServletSecurity.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/ServletSecurity.java new file mode 100644 index 00000000000..34e181ad6da --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/annotation/ServletSecurity.java @@ -0,0 +1,21 @@ +// Generated automatically from javax.servlet.annotation.ServletSecurity for testing purposes + +package javax.servlet.annotation; + +import java.lang.annotation.Annotation; +import javax.servlet.annotation.HttpConstraint; + +public interface ServletSecurity extends Annotation +{ + HttpConstraint value(); + static public enum EmptyRoleSemantic + { + DENY, PERMIT; + private EmptyRoleSemantic() {} + } + static public enum TransportGuarantee + { + CONFIDENTIAL, NONE; + private TransportGuarantee() {} + } +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspConfigDescriptor.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspConfigDescriptor.java new file mode 100644 index 00000000000..8d93a4318d7 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspConfigDescriptor.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.servlet.descriptor.JspConfigDescriptor for testing purposes + +package javax.servlet.descriptor; + +import java.util.Collection; +import javax.servlet.descriptor.JspPropertyGroupDescriptor; +import javax.servlet.descriptor.TaglibDescriptor; + +public interface JspConfigDescriptor +{ + Collection getJspPropertyGroups(); + Collection getTaglibs(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspPropertyGroupDescriptor.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspPropertyGroupDescriptor.java new file mode 100644 index 00000000000..dd852fa1088 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/JspPropertyGroupDescriptor.java @@ -0,0 +1,21 @@ +// Generated automatically from javax.servlet.descriptor.JspPropertyGroupDescriptor for testing purposes + +package javax.servlet.descriptor; + +import java.util.Collection; + +public interface JspPropertyGroupDescriptor +{ + Collection getIncludeCodas(); + Collection getIncludePreludes(); + Collection getUrlPatterns(); + String getBuffer(); + String getDefaultContentType(); + String getDeferredSyntaxAllowedAsLiteral(); + String getElIgnored(); + String getErrorOnUndeclaredNamespace(); + String getIsXml(); + String getPageEncoding(); + String getScriptingInvalid(); + String getTrimDirectiveWhitespaces(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/TaglibDescriptor.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/TaglibDescriptor.java new file mode 100644 index 00000000000..c3dd5c10473 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/descriptor/TaglibDescriptor.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.servlet.descriptor.TaglibDescriptor for testing purposes + +package javax.servlet.descriptor; + + +public interface TaglibDescriptor +{ + String getTaglibLocation(); + String getTaglibURI(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Cookie.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Cookie.java index 2033a9fd936..b5a180029be 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Cookie.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Cookie.java @@ -2,8 +2,9 @@ package javax.servlet.http; +import java.io.Serializable; -public class Cookie implements Cloneable +public class Cookie implements Cloneable, Serializable { protected Cookie() {} public Cookie(String p0, String p1){} @@ -14,10 +15,12 @@ public class Cookie implements Cloneable public String getPath(){ return null; } public String getValue(){ return null; } public boolean getSecure(){ return false; } + public boolean isHttpOnly(){ return false; } public int getMaxAge(){ return 0; } public int getVersion(){ return 0; } public void setComment(String p0){} public void setDomain(String p0){} + public void setHttpOnly(boolean p0){} public void setMaxAge(int p0){} public void setPath(String p0){} public void setSecure(boolean p0){} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletMapping.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletMapping.java new file mode 100644 index 00000000000..1b597f27773 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletMapping.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.servlet.http.HttpServletMapping for testing purposes + +package javax.servlet.http; + +import javax.servlet.http.MappingMatch; + +public interface HttpServletMapping +{ + MappingMatch getMappingMatch(); + String getMatchValue(); + String getPattern(); + String getServletName(); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequest.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequest.java index 53f6fc8a9db..9667967473a 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequest.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequest.java @@ -3,19 +3,28 @@ package javax.servlet.http; import java.security.Principal; +import java.util.Collection; import java.util.Enumeration; +import java.util.Map; import javax.servlet.ServletRequest; import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletMapping; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.servlet.http.Part; +import javax.servlet.http.PushBuilder; public interface HttpServletRequest extends ServletRequest { + Collection getParts(); Cookie[] getCookies(); - Enumeration getHeaderNames(); - Enumeration getHeaders(String p0); + Enumeration getHeaderNames(); + Enumeration getHeaders(String p0); HttpSession getSession(); HttpSession getSession(boolean p0); + Part getPart(String p0); Principal getUserPrincipal(); + String changeSessionId(); String getAuthType(); String getContextPath(); String getHeader(String p0); @@ -28,15 +37,22 @@ public interface HttpServletRequest extends ServletRequest String getRequestedSessionId(); String getServletPath(); StringBuffer getRequestURL(); + boolean authenticate(HttpServletResponse p0); boolean isRequestedSessionIdFromCookie(); boolean isRequestedSessionIdFromURL(); boolean isRequestedSessionIdFromUrl(); boolean isRequestedSessionIdValid(); boolean isUserInRole(String p0); + default HttpServletMapping getHttpServletMapping(){ return null; } + default Map getTrailerFields(){ return null; } + default PushBuilder newPushBuilder(){ return null; } + default boolean isTrailerFieldsReady(){ return false; } int getIntHeader(String p0); long getDateHeader(String p0); static String BASIC_AUTH = null; static String CLIENT_CERT_AUTH = null; static String DIGEST_AUTH = null; static String FORM_AUTH = null; + void login(String p0, String p1); + void logout(); } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequestWrapper.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequestWrapper.java new file mode 100644 index 00000000000..17ade0faf3a --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletRequestWrapper.java @@ -0,0 +1,57 @@ +// Generated automatically from javax.servlet.http.HttpServletRequestWrapper for testing purposes + +package javax.servlet.http; + +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Map; +import javax.servlet.ServletRequestWrapper; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletMapping; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.Part; +import javax.servlet.http.PushBuilder; + +public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest +{ + protected HttpServletRequestWrapper() {} + public Collection getParts(){ return null; } + public Cookie[] getCookies(){ return null; } + public Enumeration getHeaderNames(){ return null; } + public Enumeration getHeaders(String p0){ return null; } + public HttpServletMapping getHttpServletMapping(){ return null; } + public HttpServletRequestWrapper(HttpServletRequest p0){} + public HttpSession getSession(){ return null; } + public HttpSession getSession(boolean p0){ return null; } + public Map getTrailerFields(){ return null; } + public Part getPart(String p0){ return null; } + public Principal getUserPrincipal(){ return null; } + public PushBuilder newPushBuilder(){ return null; } + public String changeSessionId(){ return null; } + public String getAuthType(){ return null; } + public String getContextPath(){ return null; } + public String getHeader(String p0){ return null; } + public String getMethod(){ return null; } + public String getPathInfo(){ return null; } + public String getPathTranslated(){ return null; } + public String getQueryString(){ return null; } + public String getRemoteUser(){ return null; } + public String getRequestURI(){ return null; } + public String getRequestedSessionId(){ return null; } + public String getServletPath(){ return null; } + public StringBuffer getRequestURL(){ return null; } + public boolean authenticate(HttpServletResponse p0){ return false; } + public boolean isRequestedSessionIdFromCookie(){ return false; } + public boolean isRequestedSessionIdFromURL(){ return false; } + public boolean isRequestedSessionIdFromUrl(){ return false; } + public boolean isRequestedSessionIdValid(){ return false; } + public boolean isTrailerFieldsReady(){ return false; } + public boolean isUserInRole(String p0){ return false; } + public int getIntHeader(String p0){ return 0; } + public long getDateHeader(String p0){ return 0; } + public void login(String p0, String p1){} + public void logout(){} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponse.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponse.java new file mode 100644 index 00000000000..da902dbf30c --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponse.java @@ -0,0 +1,77 @@ +// Generated automatically from javax.servlet.http.HttpServletResponse for testing purposes + +package javax.servlet.http; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Supplier; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; + +public interface HttpServletResponse extends ServletResponse +{ + Collection getHeaderNames(); + Collection getHeaders(String p0); + String encodeRedirectURL(String p0); + String encodeRedirectUrl(String p0); + String encodeURL(String p0); + String encodeUrl(String p0); + String getHeader(String p0); + boolean containsHeader(String p0); + default Supplier> getTrailerFields(){ return null; } + default void setTrailerFields(Supplier> p0){} + int getStatus(); + static int SC_ACCEPTED = 0; + static int SC_BAD_GATEWAY = 0; + static int SC_BAD_REQUEST = 0; + static int SC_CONFLICT = 0; + static int SC_CONTINUE = 0; + static int SC_CREATED = 0; + static int SC_EXPECTATION_FAILED = 0; + static int SC_FORBIDDEN = 0; + static int SC_FOUND = 0; + static int SC_GATEWAY_TIMEOUT = 0; + static int SC_GONE = 0; + static int SC_HTTP_VERSION_NOT_SUPPORTED = 0; + static int SC_INTERNAL_SERVER_ERROR = 0; + static int SC_LENGTH_REQUIRED = 0; + static int SC_METHOD_NOT_ALLOWED = 0; + static int SC_MOVED_PERMANENTLY = 0; + static int SC_MOVED_TEMPORARILY = 0; + static int SC_MULTIPLE_CHOICES = 0; + static int SC_NON_AUTHORITATIVE_INFORMATION = 0; + static int SC_NOT_ACCEPTABLE = 0; + static int SC_NOT_FOUND = 0; + static int SC_NOT_IMPLEMENTED = 0; + static int SC_NOT_MODIFIED = 0; + static int SC_NO_CONTENT = 0; + static int SC_OK = 0; + static int SC_PARTIAL_CONTENT = 0; + static int SC_PAYMENT_REQUIRED = 0; + static int SC_PRECONDITION_FAILED = 0; + static int SC_PROXY_AUTHENTICATION_REQUIRED = 0; + static int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 0; + static int SC_REQUEST_ENTITY_TOO_LARGE = 0; + static int SC_REQUEST_TIMEOUT = 0; + static int SC_REQUEST_URI_TOO_LONG = 0; + static int SC_RESET_CONTENT = 0; + static int SC_SEE_OTHER = 0; + static int SC_SERVICE_UNAVAILABLE = 0; + static int SC_SWITCHING_PROTOCOLS = 0; + static int SC_TEMPORARY_REDIRECT = 0; + static int SC_UNAUTHORIZED = 0; + static int SC_UNSUPPORTED_MEDIA_TYPE = 0; + static int SC_USE_PROXY = 0; + void addCookie(Cookie p0); + void addDateHeader(String p0, long p1); + void addHeader(String p0, String p1); + void addIntHeader(String p0, int p1); + void sendError(int p0); + void sendError(int p0, String p1); + void sendRedirect(String p0); + void setDateHeader(String p0, long p1); + void setHeader(String p0, String p1); + void setIntHeader(String p0, int p1); + void setStatus(int p0); + void setStatus(int p0, String p1); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponseWrapper.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponseWrapper.java new file mode 100644 index 00000000000..01f33f73794 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpServletResponseWrapper.java @@ -0,0 +1,39 @@ +// Generated automatically from javax.servlet.http.HttpServletResponseWrapper for testing purposes + +package javax.servlet.http; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Supplier; +import javax.servlet.ServletResponseWrapper; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +public class HttpServletResponseWrapper extends ServletResponseWrapper implements HttpServletResponse +{ + protected HttpServletResponseWrapper() {} + public Collection getHeaderNames(){ return null; } + public Collection getHeaders(String p0){ return null; } + public HttpServletResponseWrapper(HttpServletResponse p0){} + public String encodeRedirectURL(String p0){ return null; } + public String encodeRedirectUrl(String p0){ return null; } + public String encodeURL(String p0){ return null; } + public String encodeUrl(String p0){ return null; } + public String getHeader(String p0){ return null; } + public Supplier> getTrailerFields(){ return null; } + public boolean containsHeader(String p0){ return false; } + public int getStatus(){ return 0; } + public void addCookie(Cookie p0){} + public void addDateHeader(String p0, long p1){} + public void addHeader(String p0, String p1){} + public void addIntHeader(String p0, int p1){} + public void sendError(int p0){} + public void sendError(int p0, String p1){} + public void sendRedirect(String p0){} + public void setDateHeader(String p0, long p1){} + public void setHeader(String p0, String p1){} + public void setIntHeader(String p0, int p1){} + public void setStatus(int p0){} + public void setStatus(int p0, String p1){} + public void setTrailerFields(Supplier> p0){} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSession.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSession.java index c1153ae8aac..f8f455b1423 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSession.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSession.java @@ -8,7 +8,7 @@ import javax.servlet.http.HttpSessionContext; public interface HttpSession { - Enumeration getAttributeNames(); + Enumeration getAttributeNames(); HttpSessionContext getSessionContext(); Object getAttribute(String p0); Object getValue(String p0); diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSessionContext.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSessionContext.java index 321cd23e5be..97a77b48358 100644 --- a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSessionContext.java +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/HttpSessionContext.java @@ -7,6 +7,6 @@ import javax.servlet.http.HttpSession; public interface HttpSessionContext { - Enumeration getIds(); + Enumeration getIds(); HttpSession getSession(String p0); } diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/MappingMatch.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/MappingMatch.java new file mode 100644 index 00000000000..0432fd2ef7d --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/MappingMatch.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.servlet.http.MappingMatch for testing purposes + +package javax.servlet.http; + + +public enum MappingMatch +{ + CONTEXT_ROOT, DEFAULT, EXACT, EXTENSION, PATH; + private MappingMatch() {} +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Part.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Part.java new file mode 100644 index 00000000000..a4e599748a5 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/Part.java @@ -0,0 +1,20 @@ +// Generated automatically from javax.servlet.http.Part for testing purposes + +package javax.servlet.http; + +import java.io.InputStream; +import java.util.Collection; + +public interface Part +{ + Collection getHeaderNames(); + Collection getHeaders(String p0); + InputStream getInputStream(); + String getContentType(); + String getHeader(String p0); + String getName(); + String getSubmittedFileName(); + long getSize(); + void delete(); + void write(String p0); +} diff --git a/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/PushBuilder.java b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/PushBuilder.java new file mode 100644 index 00000000000..195e2426a83 --- /dev/null +++ b/java/ql/test/stubs/javax-servlet-2.5/javax/servlet/http/PushBuilder.java @@ -0,0 +1,23 @@ +// Generated automatically from javax.servlet.http.PushBuilder for testing purposes + +package javax.servlet.http; + +import java.util.Set; + +public interface PushBuilder +{ + PushBuilder addHeader(String p0, String p1); + PushBuilder method(String p0); + PushBuilder path(String p0); + PushBuilder queryString(String p0); + PushBuilder removeHeader(String p0); + PushBuilder sessionId(String p0); + PushBuilder setHeader(String p0, String p1); + Set getHeaderNames(); + String getHeader(String p0); + String getMethod(); + String getPath(); + String getQueryString(); + String getSessionId(); + void push(); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpMessage.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpMessage.java new file mode 100644 index 00000000000..a7a3645e0d4 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpMessage.java @@ -0,0 +1,10 @@ +// Generated automatically from org.springframework.http.HttpMessage for testing purposes + +package org.springframework.http; + +import org.springframework.http.HttpHeaders; + +public interface HttpMessage +{ + HttpHeaders getHeaders(); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpRequest.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpRequest.java new file mode 100644 index 00000000000..f781391d9ca --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/HttpRequest.java @@ -0,0 +1,14 @@ +// Generated automatically from org.springframework.http.HttpRequest for testing purposes + +package org.springframework.http; + +import java.net.URI; +import org.springframework.http.HttpMessage; +import org.springframework.http.HttpMethod; + +public interface HttpRequest extends HttpMessage +{ + String getMethodValue(); + URI getURI(); + default HttpMethod getMethod(){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/PathContainer.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/PathContainer.java new file mode 100644 index 00000000000..fc2b6f0725f --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/PathContainer.java @@ -0,0 +1,28 @@ +// Generated automatically from org.springframework.http.server.PathContainer for testing purposes + +package org.springframework.http.server; + +import java.util.List; + +public interface PathContainer +{ + List elements(); + String value(); + default PathContainer subPath(int p0){ return null; } + default PathContainer subPath(int p0, int p1){ return null; } + static PathContainer parsePath(String p0){ return null; } + static PathContainer parsePath(String p0, PathContainer.Options p1){ return null; } + static public class Options + { + protected Options() {} + public boolean shouldDecodeAndParseSegments(){ return false; } + public char separator(){ return '0'; } + public static PathContainer.Options HTTP_PATH = null; + public static PathContainer.Options MESSAGE_ROUTE = null; + public static PathContainer.Options create(char p0, boolean p1){ return null; } + } + static public interface Element + { + String value(); + } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/RequestPath.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/RequestPath.java new file mode 100644 index 00000000000..7cae24a3ced --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/http/server/RequestPath.java @@ -0,0 +1,15 @@ +// Generated automatically from org.springframework.http.server.RequestPath for testing purposes + +package org.springframework.http.server; + +import java.net.URI; +import org.springframework.http.server.PathContainer; + +public interface RequestPath extends PathContainer +{ + PathContainer contextPath(); + PathContainer pathWithinApplication(); + RequestPath modifyContextPath(String p0); + static RequestPath parse(String p0, String p1){ return null; } + static RequestPath parse(URI p0, String p1){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/AbstractUriTemplateHandler.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/AbstractUriTemplateHandler.java new file mode 100644 index 00000000000..d4c1da33c56 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/AbstractUriTemplateHandler.java @@ -0,0 +1,20 @@ +// Generated automatically from org.springframework.web.util.AbstractUriTemplateHandler for testing purposes + +package org.springframework.web.util; + +import java.net.URI; +import java.util.Map; +import org.springframework.web.util.UriTemplateHandler; + +abstract public class AbstractUriTemplateHandler implements UriTemplateHandler +{ + protected abstract URI expandInternal(String p0, Map p1); + protected abstract URI expandInternal(String p0, Object... p1); + public AbstractUriTemplateHandler(){} + public Map getDefaultUriVariables(){ return null; } + public String getBaseUrl(){ return null; } + public URI expand(String p0, Map p1){ return null; } + public URI expand(String p0, Object... p1){ return null; } + public void setBaseUrl(String p0){} + public void setDefaultUriVariables(Map p0){} +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingRequestWrapper.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingRequestWrapper.java new file mode 100644 index 00000000000..40ca55d7d0b --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingRequestWrapper.java @@ -0,0 +1,26 @@ +// Generated automatically from org.springframework.web.util.ContentCachingRequestWrapper for testing purposes + +package org.springframework.web.util; + +import java.io.BufferedReader; +import java.util.Enumeration; +import java.util.Map; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class ContentCachingRequestWrapper extends HttpServletRequestWrapper +{ + protected ContentCachingRequestWrapper() {} + protected void handleContentOverflow(int p0){} + public BufferedReader getReader(){ return null; } + public ContentCachingRequestWrapper(HttpServletRequest p0){} + public ContentCachingRequestWrapper(HttpServletRequest p0, int p1){} + public Enumeration getParameterNames(){ return null; } + public Map getParameterMap(){ return null; } + public ServletInputStream getInputStream(){ return null; } + public String getCharacterEncoding(){ return null; } + public String getParameter(String p0){ return null; } + public String[] getParameterValues(String p0){ return null; } + public byte[] getContentAsByteArray(){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingResponseWrapper.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingResponseWrapper.java new file mode 100644 index 00000000000..e83a09001c4 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ContentCachingResponseWrapper.java @@ -0,0 +1,32 @@ +// Generated automatically from org.springframework.web.util.ContentCachingResponseWrapper for testing purposes + +package org.springframework.web.util; + +import java.io.InputStream; +import java.io.PrintWriter; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +public class ContentCachingResponseWrapper extends HttpServletResponseWrapper +{ + protected ContentCachingResponseWrapper() {} + protected void copyBodyToResponse(boolean p0){} + public ContentCachingResponseWrapper(HttpServletResponse p0){} + public InputStream getContentInputStream(){ return null; } + public PrintWriter getWriter(){ return null; } + public ServletOutputStream getOutputStream(){ return null; } + public byte[] getContentAsByteArray(){ return null; } + public int getContentSize(){ return 0; } + public int getStatusCode(){ return 0; } + public void copyBodyToResponse(){} + public void flushBuffer(){} + public void reset(){} + public void resetBuffer(){} + public void sendError(int p0){} + public void sendError(int p0, String p1){} + public void sendRedirect(String p0){} + public void setBufferSize(int p0){} + public void setContentLength(int p0){} + public void setContentLengthLong(long p0){} +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/CookieGenerator.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/CookieGenerator.java new file mode 100644 index 00000000000..7c376c3dff6 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/CookieGenerator.java @@ -0,0 +1,29 @@ +// Generated automatically from org.springframework.web.util.CookieGenerator for testing purposes + +package org.springframework.web.util; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; + +public class CookieGenerator +{ + protected Cookie createCookie(String p0){ return null; } + protected final Log logger = null; + public CookieGenerator(){} + public Integer getCookieMaxAge(){ return null; } + public String getCookieDomain(){ return null; } + public String getCookieName(){ return null; } + public String getCookiePath(){ return null; } + public boolean isCookieHttpOnly(){ return false; } + public boolean isCookieSecure(){ return false; } + public static String DEFAULT_COOKIE_PATH = null; + public void addCookie(HttpServletResponse p0, String p1){} + public void removeCookie(HttpServletResponse p0){} + public void setCookieDomain(String p0){} + public void setCookieHttpOnly(boolean p0){} + public void setCookieMaxAge(Integer p0){} + public void setCookieName(String p0){} + public void setCookiePath(String p0){} + public void setCookieSecure(boolean p0){} +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/DefaultUriBuilderFactory.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/DefaultUriBuilderFactory.java new file mode 100644 index 00000000000..5665186245e --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/DefaultUriBuilderFactory.java @@ -0,0 +1,31 @@ +// Generated automatically from org.springframework.web.util.DefaultUriBuilderFactory for testing purposes + +package org.springframework.web.util; + +import java.net.URI; +import java.util.Map; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriBuilderFactory; +import org.springframework.web.util.UriComponentsBuilder; + +public class DefaultUriBuilderFactory implements UriBuilderFactory +{ + public DefaultUriBuilderFactory(){} + public DefaultUriBuilderFactory(String p0){} + public DefaultUriBuilderFactory(UriComponentsBuilder p0){} + public DefaultUriBuilderFactory.EncodingMode getEncodingMode(){ return null; } + public Map getDefaultUriVariables(){ return null; } + public URI expand(String p0, Map p1){ return null; } + public URI expand(String p0, Object... p1){ return null; } + public UriBuilder builder(){ return null; } + public UriBuilder uriString(String p0){ return null; } + public boolean shouldParsePath(){ return false; } + public void setDefaultUriVariables(Map p0){} + public void setEncodingMode(DefaultUriBuilderFactory.EncodingMode p0){} + public void setParsePath(boolean p0){} + static public enum EncodingMode + { + NONE, TEMPLATE_AND_VALUES, URI_COMPONENT, VALUES_ONLY; + private EncodingMode() {} + } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/HtmlUtils.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/HtmlUtils.java new file mode 100644 index 00000000000..54a9f626825 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/HtmlUtils.java @@ -0,0 +1,16 @@ +// Generated automatically from org.springframework.web.util.HtmlUtils for testing purposes + +package org.springframework.web.util; + + +abstract public class HtmlUtils +{ + public HtmlUtils(){} + public static String htmlEscape(String p0){ return null; } + public static String htmlEscape(String p0, String p1){ return null; } + public static String htmlEscapeDecimal(String p0){ return null; } + public static String htmlEscapeDecimal(String p0, String p1){ return null; } + public static String htmlEscapeHex(String p0){ return null; } + public static String htmlEscapeHex(String p0, String p1){ return null; } + public static String htmlUnescape(String p0){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletContextPropertyUtils.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletContextPropertyUtils.java new file mode 100644 index 00000000000..5bbd8972485 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletContextPropertyUtils.java @@ -0,0 +1,12 @@ +// Generated automatically from org.springframework.web.util.ServletContextPropertyUtils for testing purposes + +package org.springframework.web.util; + +import javax.servlet.ServletContext; + +abstract public class ServletContextPropertyUtils +{ + public ServletContextPropertyUtils(){} + public static String resolvePlaceholders(String p0, ServletContext p1){ return null; } + public static String resolvePlaceholders(String p0, ServletContext p1, boolean p2){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletRequestPathUtils.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletRequestPathUtils.java new file mode 100644 index 00000000000..01b8ed6138d --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/ServletRequestPathUtils.java @@ -0,0 +1,21 @@ +// Generated automatically from org.springframework.web.util.ServletRequestPathUtils for testing purposes + +package org.springframework.web.util; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.server.RequestPath; + +abstract public class ServletRequestPathUtils +{ + public ServletRequestPathUtils(){} + public static Object getCachedPath(ServletRequest p0){ return null; } + public static RequestPath getParsedRequestPath(ServletRequest p0){ return null; } + public static RequestPath parseAndCache(HttpServletRequest p0){ return null; } + public static String PATH_ATTRIBUTE = null; + public static String getCachedPathValue(ServletRequest p0){ return null; } + public static boolean hasCachedPath(ServletRequest p0){ return false; } + public static boolean hasParsedRequestPath(ServletRequest p0){ return false; } + public static void clearParsedRequestPath(ServletRequest p0){} + public static void setParsedRequestPath(RequestPath p0, ServletRequest p1){} +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilder.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilder.java new file mode 100644 index 00000000000..f241d137257 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilder.java @@ -0,0 +1,33 @@ +// Generated automatically from org.springframework.web.util.UriBuilder for testing purposes + +package org.springframework.web.util; + +import java.net.URI; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import org.springframework.util.MultiValueMap; + +public interface UriBuilder +{ + URI build(Map p0); + URI build(Object... p0); + UriBuilder fragment(String p0); + UriBuilder host(String p0); + UriBuilder path(String p0); + UriBuilder pathSegment(String... p0); + UriBuilder port(String p0); + UriBuilder port(int p0); + UriBuilder query(String p0); + UriBuilder queryParam(String p0, Collection p1); + UriBuilder queryParam(String p0, Object... p1); + UriBuilder queryParamIfPresent(String p0, Optional p1); + UriBuilder queryParams(MultiValueMap p0); + UriBuilder replacePath(String p0); + UriBuilder replaceQuery(String p0); + UriBuilder replaceQueryParam(String p0, Collection p1); + UriBuilder replaceQueryParam(String p0, Object... p1); + UriBuilder replaceQueryParams(MultiValueMap p0); + UriBuilder scheme(String p0); + UriBuilder userInfo(String p0); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilderFactory.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilderFactory.java new file mode 100644 index 00000000000..e886e5148e8 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriBuilderFactory.java @@ -0,0 +1,12 @@ +// Generated automatically from org.springframework.web.util.UriBuilderFactory for testing purposes + +package org.springframework.web.util; + +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriTemplateHandler; + +public interface UriBuilderFactory extends UriTemplateHandler +{ + UriBuilder builder(); + UriBuilder uriString(String p0); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponents.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponents.java new file mode 100644 index 00000000000..b049020ab4b --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponents.java @@ -0,0 +1,46 @@ +// Generated automatically from org.springframework.web.util.UriComponents for testing purposes + +package org.springframework.web.util; + +import java.io.Serializable; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.function.UnaryOperator; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriComponentsBuilder; + +abstract public class UriComponents implements Serializable +{ + protected UriComponents() {} + abstract UriComponents expandInternal(UriComponents.UriTemplateVariables p0); + protected UriComponents(String p0, String p1){} + protected abstract void copyToUriComponentsBuilder(UriComponentsBuilder p0); + public abstract List getPathSegments(); + public abstract MultiValueMap getQueryParams(); + public abstract String getHost(); + public abstract String getPath(); + public abstract String getQuery(); + public abstract String getSchemeSpecificPart(); + public abstract String getUserInfo(); + public abstract String toUriString(); + public abstract URI toUri(); + public abstract UriComponents encode(Charset p0); + public abstract UriComponents normalize(); + public abstract int getPort(); + public final String getFragment(){ return null; } + public final String getScheme(){ return null; } + public final String toString(){ return null; } + public final UriComponents encode(){ return null; } + public final UriComponents expand(Map p0){ return null; } + public final UriComponents expand(Object... p0){ return null; } + public final UriComponents expand(UriComponents.UriTemplateVariables p0){ return null; } + static String expandUriComponent(String p0, UriComponents.UriTemplateVariables p1){ return null; } + static String expandUriComponent(String p0, UriComponents.UriTemplateVariables p1, UnaryOperator p2){ return null; } + static public interface UriTemplateVariables + { + Object getValue(String p0); + static Object SKIP_VALUE = null; + } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponentsBuilder.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponentsBuilder.java new file mode 100644 index 00000000000..e0d1caef9e6 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriComponentsBuilder.java @@ -0,0 +1,63 @@ +// Generated automatically from org.springframework.web.util.UriComponentsBuilder for testing purposes + +package org.springframework.web.util; + +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpRequest; +import org.springframework.util.MultiValueMap; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriComponents; + +public class UriComponentsBuilder implements Cloneable, UriBuilder +{ + UriComponentsBuilder adaptFromForwardedHeaders(HttpHeaders p0){ return null; } + protected UriComponentsBuilder(){} + protected UriComponentsBuilder(UriComponentsBuilder p0){} + public Object clone(){ return null; } + public String toUriString(){ return null; } + public URI build(Map p0){ return null; } + public URI build(Object... p0){ return null; } + public UriComponents build(){ return null; } + public UriComponents build(boolean p0){ return null; } + public UriComponents buildAndExpand(Map p0){ return null; } + public UriComponents buildAndExpand(Object... p0){ return null; } + public UriComponentsBuilder cloneBuilder(){ return null; } + public UriComponentsBuilder encode(Charset p0){ return null; } + public UriComponentsBuilder fragment(String p0){ return null; } + public UriComponentsBuilder host(String p0){ return null; } + public UriComponentsBuilder path(String p0){ return null; } + public UriComponentsBuilder pathSegment(String... p0){ return null; } + public UriComponentsBuilder port(String p0){ return null; } + public UriComponentsBuilder port(int p0){ return null; } + public UriComponentsBuilder query(String p0){ return null; } + public UriComponentsBuilder queryParam(String p0, Collection p1){ return null; } + public UriComponentsBuilder queryParam(String p0, Object... p1){ return null; } + public UriComponentsBuilder queryParamIfPresent(String p0, Optional p1){ return null; } + public UriComponentsBuilder queryParams(MultiValueMap p0){ return null; } + public UriComponentsBuilder replacePath(String p0){ return null; } + public UriComponentsBuilder replaceQuery(String p0){ return null; } + public UriComponentsBuilder replaceQueryParam(String p0, Collection p1){ return null; } + public UriComponentsBuilder replaceQueryParam(String p0, Object... p1){ return null; } + public UriComponentsBuilder replaceQueryParams(MultiValueMap p0){ return null; } + public UriComponentsBuilder scheme(String p0){ return null; } + public UriComponentsBuilder schemeSpecificPart(String p0){ return null; } + public UriComponentsBuilder uri(URI p0){ return null; } + public UriComponentsBuilder uriComponents(UriComponents p0){ return null; } + public UriComponentsBuilder uriVariables(Map p0){ return null; } + public UriComponentsBuilder userInfo(String p0){ return null; } + public final UriComponentsBuilder encode(){ return null; } + public static InetSocketAddress parseForwardedFor(HttpRequest p0, InetSocketAddress p1){ return null; } + public static UriComponentsBuilder fromHttpRequest(HttpRequest p0){ return null; } + public static UriComponentsBuilder fromHttpUrl(String p0){ return null; } + public static UriComponentsBuilder fromOriginHeader(String p0){ return null; } + public static UriComponentsBuilder fromPath(String p0){ return null; } + public static UriComponentsBuilder fromUri(URI p0){ return null; } + public static UriComponentsBuilder fromUriString(String p0){ return null; } + public static UriComponentsBuilder newInstance(){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplate.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplate.java new file mode 100644 index 00000000000..9c4ffacaa93 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplate.java @@ -0,0 +1,20 @@ +// Generated automatically from org.springframework.web.util.UriTemplate for testing purposes + +package org.springframework.web.util; + +import java.io.Serializable; +import java.net.URI; +import java.util.List; +import java.util.Map; + +public class UriTemplate implements Serializable +{ + protected UriTemplate() {} + public List getVariableNames(){ return null; } + public Map match(String p0){ return null; } + public String toString(){ return null; } + public URI expand(Map p0){ return null; } + public URI expand(Object... p0){ return null; } + public UriTemplate(String p0){} + public boolean matches(String p0){ return false; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplateHandler.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplateHandler.java new file mode 100644 index 00000000000..a09368ba3cb --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriTemplateHandler.java @@ -0,0 +1,12 @@ +// Generated automatically from org.springframework.web.util.UriTemplateHandler for testing purposes + +package org.springframework.web.util; + +import java.net.URI; +import java.util.Map; + +public interface UriTemplateHandler +{ + URI expand(String p0, Map p1); + URI expand(String p0, Object... p1); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriUtils.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriUtils.java new file mode 100644 index 00000000000..691c8e45e1a --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UriUtils.java @@ -0,0 +1,40 @@ +// Generated automatically from org.springframework.web.util.UriUtils for testing purposes + +package org.springframework.web.util; + +import java.nio.charset.Charset; +import java.util.Map; +import org.springframework.util.MultiValueMap; + +abstract public class UriUtils +{ + public UriUtils(){} + public static Map encodeUriVariables(Map p0){ return null; } + public static MultiValueMap encodeQueryParams(MultiValueMap p0){ return null; } + public static Object[] encodeUriVariables(Object... p0){ return null; } + public static String decode(String p0, Charset p1){ return null; } + public static String decode(String p0, String p1){ return null; } + public static String encode(String p0, Charset p1){ return null; } + public static String encode(String p0, String p1){ return null; } + public static String encodeAuthority(String p0, Charset p1){ return null; } + public static String encodeAuthority(String p0, String p1){ return null; } + public static String encodeFragment(String p0, Charset p1){ return null; } + public static String encodeFragment(String p0, String p1){ return null; } + public static String encodeHost(String p0, Charset p1){ return null; } + public static String encodeHost(String p0, String p1){ return null; } + public static String encodePath(String p0, Charset p1){ return null; } + public static String encodePath(String p0, String p1){ return null; } + public static String encodePathSegment(String p0, Charset p1){ return null; } + public static String encodePathSegment(String p0, String p1){ return null; } + public static String encodePort(String p0, Charset p1){ return null; } + public static String encodePort(String p0, String p1){ return null; } + public static String encodeQuery(String p0, Charset p1){ return null; } + public static String encodeQuery(String p0, String p1){ return null; } + public static String encodeQueryParam(String p0, Charset p1){ return null; } + public static String encodeQueryParam(String p0, String p1){ return null; } + public static String encodeScheme(String p0, Charset p1){ return null; } + public static String encodeScheme(String p0, String p1){ return null; } + public static String encodeUserInfo(String p0, Charset p1){ return null; } + public static String encodeUserInfo(String p0, String p1){ return null; } + public static String extractFileExtension(String p0){ return null; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UrlPathHelper.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UrlPathHelper.java new file mode 100644 index 00000000000..acabbbb7de7 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/UrlPathHelper.java @@ -0,0 +1,44 @@ +// Generated automatically from org.springframework.web.util.UrlPathHelper for testing purposes + +package org.springframework.web.util; + +import java.util.Map; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import org.springframework.util.MultiValueMap; + +public class UrlPathHelper +{ + protected String determineEncoding(HttpServletRequest p0){ return null; } + protected String getDefaultEncoding(){ return null; } + protected String getPathWithinServletMapping(HttpServletRequest p0, String p1){ return null; } + public Map decodePathVariables(HttpServletRequest p0, Map p1){ return null; } + public MultiValueMap decodeMatrixVariables(HttpServletRequest p0, MultiValueMap p1){ return null; } + public String decodeRequestString(HttpServletRequest p0, String p1){ return null; } + public String getContextPath(HttpServletRequest p0){ return null; } + public String getLookupPathForRequest(HttpServletRequest p0){ return null; } + public String getLookupPathForRequest(HttpServletRequest p0, String p1){ return null; } + public String getOriginatingContextPath(HttpServletRequest p0){ return null; } + public String getOriginatingQueryString(HttpServletRequest p0){ return null; } + public String getOriginatingRequestUri(HttpServletRequest p0){ return null; } + public String getOriginatingServletPath(HttpServletRequest p0){ return null; } + public String getPathWithinApplication(HttpServletRequest p0){ return null; } + public String getPathWithinServletMapping(HttpServletRequest p0){ return null; } + public String getRequestUri(HttpServletRequest p0){ return null; } + public String getServletPath(HttpServletRequest p0){ return null; } + public String removeSemicolonContent(String p0){ return null; } + public String resolveAndCacheLookupPath(HttpServletRequest p0){ return null; } + public UrlPathHelper(){} + public boolean isUrlDecode(){ return false; } + public boolean shouldRemoveSemicolonContent(){ return false; } + public static String PATH_ATTRIBUTE = null; + public static String getResolvedLookupPath(ServletRequest p0){ return null; } + public static UrlPathHelper defaultInstance = null; + public static UrlPathHelper rawPathInstance = null; + public void setAlwaysUseFullPath(boolean p0){} + public void setDefaultEncoding(String p0){} + public void setRemoveSemicolonContent(boolean p0){} + public void setUrlDecode(boolean p0){} + static Boolean websphereComplianceFlag = null; + static boolean servlet4Present = false; +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/WebUtils.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/WebUtils.java new file mode 100644 index 00000000000..84138bcea47 --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/web/util/WebUtils.java @@ -0,0 +1,69 @@ +// Generated automatically from org.springframework.web.util.WebUtils for testing purposes + +package org.springframework.web.util; + +import java.io.File; +import java.util.Collection; +import java.util.Map; +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import org.springframework.http.HttpRequest; +import org.springframework.util.MultiValueMap; + +abstract public class WebUtils +{ + public WebUtils(){} + public static T getNativeRequest(ServletRequest p0, Class p1){ return null; } + public static T getNativeResponse(ServletResponse p0, Class p1){ return null; } + public static Boolean getDefaultHtmlEscape(ServletContext p0){ return null; } + public static Boolean getResponseEncodedHtmlEscape(ServletContext p0){ return null; } + public static Cookie getCookie(HttpServletRequest p0, String p1){ return null; } + public static File getTempDir(ServletContext p0){ return null; } + public static Map getParametersStartingWith(ServletRequest p0, String p1){ return null; } + public static MultiValueMap parseMatrixVariables(String p0){ return null; } + public static Object getRequiredSessionAttribute(HttpServletRequest p0, String p1){ return null; } + public static Object getSessionAttribute(HttpServletRequest p0, String p1){ return null; } + public static Object getSessionMutex(HttpSession p0){ return null; } + public static String CONTENT_TYPE_CHARSET_PREFIX = null; + public static String DEFAULT_CHARACTER_ENCODING = null; + public static String DEFAULT_WEB_APP_ROOT_KEY = null; + public static String ERROR_EXCEPTION_ATTRIBUTE = null; + public static String ERROR_EXCEPTION_TYPE_ATTRIBUTE = null; + public static String ERROR_MESSAGE_ATTRIBUTE = null; + public static String ERROR_REQUEST_URI_ATTRIBUTE = null; + public static String ERROR_SERVLET_NAME_ATTRIBUTE = null; + public static String ERROR_STATUS_CODE_ATTRIBUTE = null; + public static String FORWARD_CONTEXT_PATH_ATTRIBUTE = null; + public static String FORWARD_PATH_INFO_ATTRIBUTE = null; + public static String FORWARD_QUERY_STRING_ATTRIBUTE = null; + public static String FORWARD_REQUEST_URI_ATTRIBUTE = null; + public static String FORWARD_SERVLET_PATH_ATTRIBUTE = null; + public static String HTML_ESCAPE_CONTEXT_PARAM = null; + public static String INCLUDE_CONTEXT_PATH_ATTRIBUTE = null; + public static String INCLUDE_PATH_INFO_ATTRIBUTE = null; + public static String INCLUDE_QUERY_STRING_ATTRIBUTE = null; + public static String INCLUDE_REQUEST_URI_ATTRIBUTE = null; + public static String INCLUDE_SERVLET_PATH_ATTRIBUTE = null; + public static String RESPONSE_ENCODED_HTML_ESCAPE_CONTEXT_PARAM = null; + public static String SESSION_MUTEX_ATTRIBUTE = null; + public static String TEMP_DIR_CONTEXT_ATTRIBUTE = null; + public static String WEB_APP_ROOT_KEY_PARAM = null; + public static String findParameterValue(Map p0, String p1){ return null; } + public static String findParameterValue(ServletRequest p0, String p1){ return null; } + public static String getRealPath(ServletContext p0, String p1){ return null; } + public static String getSessionId(HttpServletRequest p0){ return null; } + public static String[] SUBMIT_IMAGE_SUFFIXES = null; + public static boolean hasSubmitParameter(ServletRequest p0, String p1){ return false; } + public static boolean isIncludeRequest(ServletRequest p0){ return false; } + public static boolean isSameOrigin(HttpRequest p0){ return false; } + public static boolean isValidOrigin(HttpRequest p0, Collection p1){ return false; } + public static void clearErrorRequestAttributes(HttpServletRequest p0){} + public static void exposeErrorRequestAttributes(HttpServletRequest p0, Throwable p1, String p2){} + public static void removeWebAppRootSystemProperty(ServletContext p0){} + public static void setSessionAttribute(HttpServletRequest p0, String p1, Object p2){} + public static void setWebAppRootSystemProperty(ServletContext p0){} +} From d86dffbb5dfce0cf40f6bec1175a0850775e056a Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 14 Jul 2021 04:28:53 -0700 Subject: [PATCH 239/429] Add tests for Spring web.util --- .../frameworks/spring/webutil/Test.java | 2585 +++++++++++++++++ .../frameworks/spring/webutil/options | 1 + .../frameworks/spring/webutil/test.expected | 0 .../frameworks/spring/webutil/test.ql | 52 + 4 files changed, 2638 insertions(+) create mode 100644 java/ql/test/library-tests/frameworks/spring/webutil/Test.java create mode 100644 java/ql/test/library-tests/frameworks/spring/webutil/options create mode 100644 java/ql/test/library-tests/frameworks/spring/webutil/test.expected create mode 100644 java/ql/test/library-tests/frameworks/spring/webutil/test.ql diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/Test.java b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java new file mode 100644 index 00000000000..e2856917041 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java @@ -0,0 +1,2585 @@ +package generatedtest; + +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.http.HttpRequest; +import org.springframework.http.server.RequestPath; +import org.springframework.util.MultiValueMap; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.web.util.AbstractUriTemplateHandler; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; +import org.springframework.web.util.CookieGenerator; +import org.springframework.web.util.DefaultUriBuilderFactory; +import org.springframework.web.util.HtmlUtils; +import org.springframework.web.util.ServletContextPropertyUtils; +import org.springframework.web.util.ServletRequestPathUtils; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriBuilderFactory; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriTemplate; +import org.springframework.web.util.UriTemplateHandler; +import org.springframework.web.util.UriUtils; +import org.springframework.web.util.UrlPathHelper; +import org.springframework.web.util.WebUtils; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + class StubUriTemplateVariables extends HashMap implements UriComponents.UriTemplateVariables { + StubUriTemplateVariables(Map m) { super(m); } + + public Object getValue(String name) { return this.get(name); } + } + + Object getElement(Collection container) { return container.iterator().next(); } + T getMapKey(Map m) { return m.keySet().iterator().next(); } + T getMapValue(Map m) { return m.get(null); } + Map newMapWithKey(Object element) { return Map.of(element, null); } + Map newMapWithValue(Object element) { return Map.of(null, element); } + MultiValueMap newMultiValueMapWithKey(Object element) { return new LinkedMultiValueMap(Map.of(element, null)); } + MultiValueMap newMultiValueMapWithValue(Object element) { MultiValueMap m = new LinkedMultiValueMap(); m.put(null, element); return m; } + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "org.springframework.web.util;AbstractUriTemplateHandler;true;getBaseUrl;;;Argument[-1];ReturnValue;taint" + String out = null; + AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); + out = in.getBaseUrl(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;AbstractUriTemplateHandler;true;setBaseUrl;;;Argument[0];Argument[-1];taint" + AbstractUriTemplateHandler out = null; + String in = (String)source(); + out.setBaseUrl(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;AbstractUriTemplateHandler;true;setDefaultUriVariables;;;Argument[0];Argument[-1];taint" + AbstractUriTemplateHandler out = null; + Map in = (Map)source(); + out.setDefaultUriVariables(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingRequestWrapper;false;ContentCachingRequestWrapper;;;Argument[0];Argument[-1];taint" + ContentCachingRequestWrapper out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = new ContentCachingRequestWrapper(in, 0); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingRequestWrapper;false;ContentCachingRequestWrapper;;;Argument[0];Argument[-1];taint" + ContentCachingRequestWrapper out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = new ContentCachingRequestWrapper(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingRequestWrapper;false;getContentAsByteArray;;;Argument[-1];ReturnValue;taint" + byte[] out = null; + ContentCachingRequestWrapper in = (ContentCachingRequestWrapper)source(); + out = in.getContentAsByteArray(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingResponseWrapper;false;ContentCachingResponseWrapper;;;Argument[0];Argument[-1];taint" + ContentCachingResponseWrapper out = null; + HttpServletResponse in = (HttpServletResponse)source(); + out = new ContentCachingResponseWrapper(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentAsByteArray;;;Argument[-1];ReturnValue;taint" + byte[] out = null; + ContentCachingResponseWrapper in = (ContentCachingResponseWrapper)source(); + out = in.getContentAsByteArray(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentInputStream;;;Argument[-1];ReturnValue;taint" + InputStream out = null; + ContentCachingResponseWrapper in = (ContentCachingResponseWrapper)source(); + out = in.getContentInputStream(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[-1];taint" + DefaultUriBuilderFactory out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = new DefaultUriBuilderFactory(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[-1];taint" + DefaultUriBuilderFactory out = null; + String in = (String)source(); + out = new DefaultUriBuilderFactory(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;builder;;;Argument[-1];ReturnValue;taint" + UriBuilder out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.builder(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + DefaultUriBuilderFactory instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + DefaultUriBuilderFactory instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + DefaultUriBuilderFactory instance = null; + out = instance.expand(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + DefaultUriBuilderFactory instance = null; + out = instance.expand(in, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.expand((String)null, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.expand((String)null, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;getDefaultUriVariables;;;Argument[-1];MapValue of ReturnValue;taint" + Map out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.getDefaultUriVariables(); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;setDefaultUriVariables;;;MapValue of Argument[0];Argument[-1];taint" + DefaultUriBuilderFactory out = null; + Map in = Map.of(null, source()); + out.setDefaultUriVariables(in); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;DefaultUriBuilderFactory;false;uriString;;;Argument[-1];ReturnValue;taint" + UriBuilder out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.uriString(null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlUnescape;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlUnescape(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = ServletContextPropertyUtils.resolvePlaceholders(in, null, false); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = ServletContextPropertyUtils.resolvePlaceholders(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint" + String out = null; + ServletContext in = (ServletContext)source(); + out = ServletContextPropertyUtils.resolvePlaceholders(null, in, false); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint" + String out = null; + ServletContext in = (ServletContext)source(); + out = ServletContextPropertyUtils.resolvePlaceholders(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPath;;;Argument[0];ReturnValue;taint" + Object out = null; + ServletRequest in = (ServletRequest)source(); + out = ServletRequestPathUtils.getCachedPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPathValue;;;Argument[0];ReturnValue;taint" + String out = null; + ServletRequest in = (ServletRequest)source(); + out = ServletRequestPathUtils.getCachedPathValue(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletRequestPathUtils;false;getParsedRequestPath;;;Argument[0];ReturnValue;taint" + RequestPath out = null; + ServletRequest in = (ServletRequest)source(); + out = ServletRequestPathUtils.getParsedRequestPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletRequestPathUtils;false;parseAndCache;;;Argument[0];ReturnValue;taint" + RequestPath out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = ServletRequestPathUtils.parseAndCache(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;ServletRequestPathUtils;false;setParsedRequestPath;;;Argument[0];Argument[1];taint" + ServletRequest out = null; + RequestPath in = (RequestPath)source(); + ServletRequestPathUtils.setParsedRequestPath(in, out); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];Argument[-1];taint" + UriBuilder out = null; + Map in = newMapWithValue(source()); + out.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];Argument[-1];taint" + UriBuilder out = null; + Map in = newMapWithValue(source()); + out.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + UriBuilder instance = null; + out = instance.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + UriBuilder instance = null; + out = instance.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build(false); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build((Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build((Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build((Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriBuilder in = (UriBuilder)source(); + out = in.build((Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.fragment(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.fragment(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.fragment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.fragment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.fragment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.fragment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;host;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.host(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;host;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.host(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;host;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.host(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;host;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.host(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.path(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.path(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.path(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.path(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.path(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.path(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.pathSegment((String[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.pathSegment((String[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];Argument[-1];taint" + UriBuilder out = null; + String[] in = new String[]{(String)source()}; + out.pathSegment((String[])in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];Argument[-1];taint" + UriBuilder out = null; + String[] in = new String[]{(String)source()}; + out.pathSegment((String[])in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint" + UriBuilder out = null; + String[] in = new String[]{(String)source()}; + UriBuilder instance = null; + out = instance.pathSegment((String[])in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint" + UriBuilder out = null; + String[] in = new String[]{(String)source()}; + UriBuilder instance = null; + out = instance.pathSegment((String[])in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.port(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.port(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.port(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.port(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.port(0); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.port((String)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.port(0); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;port;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.port((String)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.query(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.query(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.query(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.query(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.query(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.query(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Collection in = List.of(source()); + out.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Collection in = List.of(source()); + out.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Collection in = List.of(source()); + UriBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Collection in = List.of(source()); + UriBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + out.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + out.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + UriBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + UriBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParamIfPresent(null, null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParamIfPresent(null, null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParamIfPresent(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.queryParamIfPresent(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParamIfPresent(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.queryParamIfPresent(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Optional in = Optional.of(source()); + out.queryParamIfPresent(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Optional in = Optional.of(source()); + out.queryParamIfPresent(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Optional in = Optional.of(source()); + UriBuilder instance = null; + out = instance.queryParamIfPresent(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Optional in = Optional.of(source()); + UriBuilder instance = null; + out = instance.queryParamIfPresent(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.queryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];Argument[-1];taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + out.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];Argument[-1];taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + out.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + out.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + out.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replacePath(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replacePath(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replacePath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replacePath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replacePath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replacePath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQuery(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQuery(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQuery(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQuery(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQuery(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQuery(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Collection in = List.of(source()); + out.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Collection in = List.of(source()); + out.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Collection in = List.of(source()); + UriBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Collection in = List.of(source()); + UriBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + out.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + out.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + UriBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriBuilder out = null; + Object[] in = new Object[]{source()}; + UriBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQueryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQueryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQueryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.replaceQueryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQueryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQueryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQueryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.replaceQueryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.replaceQueryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.scheme(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.scheme(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.scheme(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.scheme(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.scheme(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.scheme(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.userInfo(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[-1];ReturnValue;value" + UriBuilder out = null; + UriBuilder in = (UriBuilder)source(); + out = in.userInfo(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.userInfo(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];Argument[-1];taint" + UriBuilder out = null; + String in = (String)source(); + out.userInfo(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.userInfo(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilder instance = null; + out = instance.userInfo(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;builder;;;Argument[-1];ReturnValue;taint" + UriBuilder out = null; + UriBuilderFactory in = (UriBuilderFactory)source(); + out = in.builder(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;builder;;;Argument[-1];ReturnValue;taint" + UriBuilder out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.builder(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[-1..0];ReturnValue;taint" + UriBuilder out = null; + UriBuilderFactory in = (UriBuilderFactory)source(); + out = in.uriString(null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[-1..0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + UriBuilderFactory instance = null; + out = instance.uriString(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[-1..0];ReturnValue;taint" + UriBuilder out = null; + String in = (String)source(); + DefaultUriBuilderFactory instance = null; + out = instance.uriString(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[-1..0];ReturnValue;taint" + UriBuilder out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.uriString(null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents$UriTemplateVariables;true;getValue;;;MapValue of Argument[-1];ReturnValue;value" + Object out = null; + UriComponents.UriTemplateVariables in = new StubUriTemplateVariables(Map.of(null, source())); + out = in.getValue(null); + sink(out); // $hasValueFlow + } + // { + // // "org.springframework.web.util;UriComponents;false;UriComponents;;;Argument[0..1];Argument[-1];taint" + // UriComponents out = null; + // String in = (String)source(); + // out = new UriComponents(null, in); + // sink(out); // $hasTaintFlow + // } + // { + // // "org.springframework.web.util;UriComponents;false;UriComponents;;;Argument[0..1];Argument[-1];taint" + // UriComponents out = null; + // String in = (String)source(); + // out = new UriComponents(in, null); + // sink(out); // $hasTaintFlow + // } + { + // "org.springframework.web.util;UriComponents;false;encode;;;Argument[-1];ReturnValue;taint" + UriComponents out = null; + UriComponents in = (UriComponents)source(); + out = in.encode(null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;encode;;;Argument[-1];ReturnValue;taint" + UriComponents out = null; + UriComponents in = (UriComponents)source(); + out = in.encode(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint" + UriComponents out = null; + Map in = newMapWithValue(source()); + UriComponents instance = null; + out = instance.expand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint" + UriComponents out = null; + Object[] in = new Object[]{source()}; + UriComponents instance = null; + out = instance.expand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;expand;(UriTemplateVariables);;MapValue of Argument[0];ReturnValue;taint" + UriComponents out = null; + UriComponents.UriTemplateVariables in = new StubUriTemplateVariables(Map.of(null, source())); + UriComponents instance = null; + out = instance.expand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getFragment;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getFragment(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getHost;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getHost(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getPath;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getPath(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getPathSegments;;;Argument[-1];ReturnValue;taint" + List out = null; + UriComponents in = (UriComponents)source(); + out = in.getPathSegments(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getQuery;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getQuery(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[-1];Element of MapValue of ReturnValue;taint" + MultiValueMap out = null; + UriComponents in = (UriComponents)source(); + out = in.getQueryParams(); + sink(getElement((List)getMapValue(out))); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[-1];MapKey of ReturnValue;taint" + MultiValueMap out = null; + UriComponents in = (UriComponents)source(); + out = in.getQueryParams(); + sink(getMapKey(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getScheme;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getScheme(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getSchemeSpecificPart;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getSchemeSpecificPart(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;getUserInfo;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.getUserInfo(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;toUri;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriComponents in = (UriComponents)source(); + out = in.toUri(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponents;false;toUriString;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponents in = (UriComponents)source(); + out = in.toUriString(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;(Map);;MapValue of Argument[0];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + UriComponentsBuilder instance = null; + out = instance.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + UriComponentsBuilder instance = null; + out = instance.build(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[-1];ReturnValue;taint" + UriComponents out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.build(false); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[-1];ReturnValue;taint" + UriComponents out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.build(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.build((Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[-1];ReturnValue;taint" + URI out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.build((Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Map);;MapValue of Argument[0];ReturnValue;taint" + UriComponents out = null; + Map in = newMapWithValue(source()); + UriComponentsBuilder instance = null; + out = instance.buildAndExpand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint" + UriComponents out = null; + Object[] in = new Object[]{source()}; + UriComponentsBuilder instance = null; + out = instance.buildAndExpand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;cloneBuilder;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.cloneBuilder(); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.encode(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.encode(); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.fragment(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.fragment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromHttpRequest;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + HttpRequest in = (HttpRequest)source(); + out = UriComponentsBuilder.fromHttpRequest(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromHttpUrl;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + out = UriComponentsBuilder.fromHttpUrl(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromOriginHeader;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + out = UriComponentsBuilder.fromOriginHeader(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromPath;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + out = UriComponentsBuilder.fromPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromUri;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + URI in = (URI)source(); + out = UriComponentsBuilder.fromUri(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;fromUriString;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + out = UriComponentsBuilder.fromUriString(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.host(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.host(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint" + InetSocketAddress out = null; + InetSocketAddress in = (InetSocketAddress)source(); + out = UriComponentsBuilder.parseForwardedFor(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint" + InetSocketAddress out = null; + HttpRequest in = (HttpRequest)source(); + out = UriComponentsBuilder.parseForwardedFor(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.path(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.path(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.pathSegment((String[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String[] in = new String[]{(String)source()}; + UriComponentsBuilder instance = null; + out = instance.pathSegment(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;port;(String);;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.port(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.port(0); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.port((String)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.query(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.query(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriComponentsBuilder out = null; + Collection in = List.of(source()); + UriComponentsBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriComponentsBuilder out = null; + Object[] in = new Object[]{source()}; + UriComponentsBuilder instance = null; + out = instance.queryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.queryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.queryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.queryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.queryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.queryParamIfPresent(null, null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.queryParamIfPresent(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint" + UriComponentsBuilder out = null; + Optional in = Optional.of(source()); + UriComponentsBuilder instance = null; + out = instance.queryParamIfPresent(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.queryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriComponentsBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriComponentsBuilder instance = null; + out = instance.queryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.replacePath(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.replacePath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.replaceQuery(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.replaceQuery(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint" + UriComponentsBuilder out = null; + Collection in = List.of(source()); + UriComponentsBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + UriComponentsBuilder out = null; + Object[] in = new Object[]{source()}; + UriComponentsBuilder instance = null; + out = instance.replaceQueryParam((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.replaceQueryParam((String)null, (Object[])null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.replaceQueryParam((String)null, (Collection)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.replaceQueryParam(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.replaceQueryParam(in, (Collection)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.replaceQueryParams(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UriComponentsBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UriComponentsBuilder instance = null; + out = instance.replaceQueryParams(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.scheme(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.scheme(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.schemeSpecificPart(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.schemeSpecificPart(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;toUriString;;;Argument[-1];ReturnValue;taint" + String out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.toUriString(); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.uri(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + URI in = (URI)source(); + UriComponentsBuilder instance = null; + out = instance.uri(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.uriComponents(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + UriComponents in = (UriComponents)source(); + UriComponentsBuilder instance = null; + out = instance.uriComponents(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.uriVariables(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;MapValue of Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + Map in = newMapWithValue(source()); + UriComponentsBuilder instance = null; + out = instance.uriVariables(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[-1];ReturnValue;value" + UriComponentsBuilder out = null; + UriComponentsBuilder in = (UriComponentsBuilder)source(); + out = in.userInfo(null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[0];ReturnValue;taint" + UriComponentsBuilder out = null; + String in = (String)source(); + UriComponentsBuilder instance = null; + out = instance.userInfo(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplate;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + UriTemplate instance = null; + out = instance.expand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplate;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + UriTemplate instance = null; + out = instance.expand(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplate;false;getVariableNames;;;Argument[-1];Element of ReturnValue;taint" + List out = null; + UriTemplate in = (UriTemplate)source(); + out = in.getVariableNames(); + sink(getElement(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplate;false;match;;;Argument[0];MapValue of ReturnValue;taint" + Map out = null; + String in = (String)source(); + UriTemplate instance = null; + out = instance.match(in); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + UriTemplateHandler instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + DefaultUriBuilderFactory instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint" + URI out = null; + Map in = newMapWithValue(source()); + AbstractUriTemplateHandler instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + UriTemplateHandler instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + DefaultUriBuilderFactory instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint" + URI out = null; + Object[] in = new Object[]{source()}; + AbstractUriTemplateHandler instance = null; + out = instance.expand((String)null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + UriTemplateHandler in = (UriTemplateHandler)source(); + out = in.expand((String)null, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + UriTemplateHandler in = (UriTemplateHandler)source(); + out = in.expand((String)null, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + UriTemplateHandler instance = null; + out = instance.expand(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + UriTemplateHandler instance = null; + out = instance.expand(in, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + DefaultUriBuilderFactory instance = null; + out = instance.expand(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + DefaultUriBuilderFactory instance = null; + out = instance.expand(in, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + AbstractUriTemplateHandler instance = null; + out = instance.expand(in, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + String in = (String)source(); + AbstractUriTemplateHandler instance = null; + out = instance.expand(in, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.expand((String)null, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); + out = in.expand((String)null, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); + out = in.expand((String)null, (Object[])null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[-1..0];ReturnValue;taint" + URI out = null; + AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); + out = in.expand((String)null, (Map)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;decode;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.decode(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;decode;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.decode(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encode;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encode(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encode;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encode(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeAuthority;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeAuthority(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeAuthority;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeAuthority(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeFragment;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeFragment(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeFragment;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeFragment(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeHost;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeHost(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeHost;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeHost(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePath;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePath(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePath;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePath(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePathSegment;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePathSegment(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePathSegment;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePathSegment(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePort;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePort(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodePort;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodePort(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQuery;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeQuery(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQuery;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeQuery(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQueryParam;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeQueryParam(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQueryParam;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeQueryParam(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapKey of Argument[0];MapKey of ReturnValue;taint" + MultiValueMap out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + out = UriUtils.encodeQueryParams(in); + sink(getMapKey(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapValue of Argument[0];MapValue of ReturnValue;taint" + MultiValueMap out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + out = UriUtils.encodeQueryParams(in); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeScheme;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeScheme(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeScheme;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeScheme(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapKey of Argument[0];MapKey of ReturnValue;taint" + Map out = null; + Map in = newMapWithKey(source()); + out = UriUtils.encodeUriVariables(in); + sink(getMapKey(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapValue of Argument[0];MapValue of ReturnValue;taint" + Map out = null; + Map in = newMapWithValue(source()); + out = UriUtils.encodeUriVariables(in); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Object[]);;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint" + Object[] out = null; + Object[] in = new Object[]{source()}; + out = UriUtils.encodeUriVariables(in); + sink(out[0]); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeUserInfo;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeUserInfo(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;encodeUserInfo;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.encodeUserInfo(in, (Charset)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UriUtils;false;extractFileExtension;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = UriUtils.extractFileExtension(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value" + MultiValueMap out = null; + MultiValueMap in = newMultiValueMapWithKey(source()); + UrlPathHelper instance = null; + out = instance.decodeMatrixVariables(null, in); + sink(getMapKey(out)); // $hasValueFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint" + MultiValueMap out = null; + MultiValueMap in = newMultiValueMapWithValue(source()); + UrlPathHelper instance = null; + out = instance.decodeMatrixVariables(null, in); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value" + Map out = null; + Map in = newMapWithKey(source()); + UrlPathHelper instance = null; + out = instance.decodePathVariables(null, in); + sink(getMapKey(out)); // $hasValueFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint" + Map out = null; + Map in = newMapWithValue(source()); + UrlPathHelper instance = null; + out = instance.decodePathVariables(null, in); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;decodeRequestString;;;Argument[1];ReturnValue;taint" + String out = null; + String in = (String)source(); + UrlPathHelper instance = null; + out = instance.decodeRequestString(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getContextPath;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getContextPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getOriginatingContextPath;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getOriginatingContextPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getOriginatingQueryString;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getOriginatingQueryString(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getOriginatingRequestUri;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getOriginatingRequestUri(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getOriginatingServletPath;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getOriginatingServletPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getRequestUri;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getRequestUri(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getResolvedLookupPath;;;Argument[0];ReturnValue;taint" + String out = null; + ServletRequest in = (ServletRequest)source(); + out = UrlPathHelper.getResolvedLookupPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;getServletPath;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.getServletPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;removeSemicolonContent;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + UrlPathHelper instance = null; + out = instance.removeSemicolonContent(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;UrlPathHelper;false;resolveAndCacheLookupPath;;;Argument[0];ReturnValue;taint" + String out = null; + HttpServletRequest in = (HttpServletRequest)source(); + UrlPathHelper instance = null; + out = instance.resolveAndCacheLookupPath(in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;findParameterValue;(Map,String);;MapValue of Argument[0];ReturnValue;value" + String out = null; + Map in = newMapWithValue(source()); + out = WebUtils.findParameterValue(in, (String)null); + sink(out); // $hasValueFlow + } + { + // "org.springframework.web.util;WebUtils;false;findParameterValue;(ServletRequest,String);;Argument[0];ReturnValue;taint" + String out = null; + ServletRequest in = (ServletRequest)source(); + out = WebUtils.findParameterValue(in, (String)null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getCookie;;;Argument[0];ReturnValue;taint" + Cookie out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = WebUtils.getCookie(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getNativeRequest;;;Argument[0];ReturnValue;taint" + Object out = null; + ServletRequest in = (ServletRequest)source(); + out = WebUtils.getNativeRequest(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getNativeResponse;;;Argument[0];ReturnValue;taint" + Object out = null; + ServletResponse in = (ServletResponse)source(); + out = WebUtils.getNativeResponse(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapKey of ReturnValue;taint" + Map out = null; + ServletRequest in = (ServletRequest)source(); + out = WebUtils.getParametersStartingWith(in, null); + sink(getMapKey(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapValue of ReturnValue;taint" + Map out = null; + ServletRequest in = (ServletRequest)source(); + out = WebUtils.getParametersStartingWith(in, null); + sink(getMapValue(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getRealPath;;;Argument[0..1];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = WebUtils.getRealPath(null, in); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getRealPath;;;Argument[0..1];ReturnValue;taint" + String out = null; + ServletContext in = (ServletContext)source(); + out = WebUtils.getRealPath(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getRequiredSessionAttribute;;;Argument[0];ReturnValue;taint" + Object out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = WebUtils.getRequiredSessionAttribute(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;getSessionAttribute;;;Argument[0];ReturnValue;taint" + Object out = null; + HttpServletRequest in = (HttpServletRequest)source(); + out = WebUtils.getSessionAttribute(in, null); + sink(out); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapKey of ReturnValue;taint" + MultiValueMap out = null; + String in = (String)source(); + out = WebUtils.parseMatrixVariables(in); + sink(getMapKey(out)); // $hasTaintFlow + } + { + // "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapValue of ReturnValue;taint" + MultiValueMap out = null; + String in = (String)source(); + out = WebUtils.parseMatrixVariables(in); + sink(getMapValue(out)); // $hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/options b/java/ql/test/library-tests/frameworks/spring/webutil/options new file mode 100644 index 00000000000..6dc26155d1d --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/webutil/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8:${testdir}/../../../../stubs/javax-servlet-2.5:${testdir}/../../../../stubs/apache-commons-logging-1.2 diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/test.expected b/java/ql/test/library-tests/frameworks/spring/webutil/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/test.ql b/java/ql/test/library-tests/frameworks/spring/webutil/test.ql new file mode 100644 index 00000000000..6158159e1e5 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/webutil/test.ql @@ -0,0 +1,52 @@ +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.TaintTracking +import TestUtilities.InlineExpectationsTest + +class ValueFlowConf extends DataFlow::Configuration { + ValueFlowConf() { this = "qltest:valueFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class TaintFlowConf extends TaintTracking::Configuration { + TaintFlowConf() { this = "qltest:taintFlowConf" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod().hasName("source") + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().hasName("sink") + } +} + +class HasFlowTest extends InlineExpectationsTest { + HasFlowTest() { this = "HasFlowTest" } + + override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + or + tag = "hasTaintFlow" and + exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf | + conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink) + | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} From eb980e2a40b60299273c536abb4f1d91a606a4bb Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Thu, 1 Jul 2021 06:06:56 -0700 Subject: [PATCH 240/429] Add change note --- java/change-notes/2021-07-01-spring-webutil.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/change-notes/2021-07-01-spring-webutil.md diff --git a/java/change-notes/2021-07-01-spring-webutil.md b/java/change-notes/2021-07-01-spring-webutil.md new file mode 100644 index 00000000000..279fd801e01 --- /dev/null +++ b/java/change-notes/2021-07-01-spring-webutil.md @@ -0,0 +1,4 @@ +lgtm,codescanning +* Additional flow steps in the `org.springframework.web.util` package of the Spring framework have + been modelled. This may result in additional results for security queries on projects using this + framework. From 9a5c0f6c738f6bb6ad30307f688781b8e45862f3 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Tue, 3 Aug 2021 08:29:46 -0700 Subject: [PATCH 241/429] Java: Add HTML escapes as XSS sanitizers Co-Authored-By: Anders Schack-Mulligen --- java/ql/src/semmle/code/java/security/XSS.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/src/semmle/code/java/security/XSS.qll b/java/ql/src/semmle/code/java/security/XSS.qll index a24ad2e22dc..89694c8a904 100644 --- a/java/ql/src/semmle/code/java/security/XSS.qll +++ b/java/ql/src/semmle/code/java/security/XSS.qll @@ -94,6 +94,9 @@ private class DefaultXssSink extends XssSink { private class DefaultXSSSanitizer extends XssSanitizer { DefaultXSSSanitizer() { this.getType() instanceof NumericType or this.getType() instanceof BooleanType + or + // Match `org.springframework.web.util.HtmlUtils.htmlEscape` and possibly other methods like it. + this.asExpr().(MethodAccess).getMethod().getName().regexpMatch("(?i)html_?escape.*") } } From 9c1d5a70e39a047effe418109aaa59896df6db27 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 4 Aug 2021 02:34:31 -0700 Subject: [PATCH 242/429] Java: Add test for XSS sanitizer --- .../security/CWE-079/semmle/tests/SpringXSS.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java/ql/test/query-tests/security/CWE-079/semmle/tests/SpringXSS.java b/java/ql/test/query-tests/security/CWE-079/semmle/tests/SpringXSS.java index 959125caa4c..744fe853b67 100644 --- a/java/ql/test/query-tests/security/CWE-079/semmle/tests/SpringXSS.java +++ b/java/ql/test/query-tests/security/CWE-079/semmle/tests/SpringXSS.java @@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.HtmlUtils; import java.util.Optional; @@ -157,4 +158,9 @@ public class SpringXSS { return userControlled; // $xss } -} \ No newline at end of file + @GetMapping(value = "/abc") + public static String sanitizedString(String userControlled) { + return HtmlUtils.htmlEscape(userControlled); + } + +} From ed1d8550255df5f94a705322c026666d5d57c318 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Sun, 8 Aug 2021 14:25:53 -0700 Subject: [PATCH 243/429] Java: Remove redundant models from Spring web.util and fix typo --- .../java/frameworks/spring/SpringWebUtil.qll | 40 +------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll index 667d6723203..f753464ab26 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll @@ -29,7 +29,7 @@ private class FlowSummaries extends SummaryModelCsv { "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];SyntheticField[uri.Query] ofArgument[-1];taint", + "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[-1];ReturnValue;value", "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[-1];taint", @@ -40,6 +40,7 @@ private class FlowSummaries extends SummaryModelCsv { "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[-1];ReturnValue;value", + "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;MapKey of Argument[0];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[-1];ReturnValue;value", "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[-1];taint", @@ -103,48 +104,13 @@ private class FlowSummaries extends SummaryModelCsv { "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;cloneBuilder;;;Argument[-1];ReturnValue;value", "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriComponentsBuilder;false;fromHttpRequest;;;Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;fromHttpUrl;;;Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;fromOriginHeader;;;Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;fromPath;;;Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;fromUri;;;Argument[0];ReturnValue;taint", "org.springframework.web.util;UriComponentsBuilder;false;fromUriString;;;Argument[0];ReturnValue;taint", - "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint", - "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;ArrayElement of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;port;(String);;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Element of Argument[1];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;MapKey of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;MapKey of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Element of MapValue of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[-1];ReturnValue;value", "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriComponentsBuilder;false;toUriString;;;Argument[-1];ReturnValue;taint", @@ -154,8 +120,6 @@ private class FlowSummaries extends SummaryModelCsv { "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;Argument[-1];ReturnValue;value", "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;MapValue of Argument[0];Argument[-1];taint", - "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[-1];ReturnValue;value", - "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;UriTemplate;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint", "org.springframework.web.util;UriTemplate;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint", "org.springframework.web.util;UriTemplate;false;getVariableNames;;;Argument[-1];Element of ReturnValue;taint", From 814004e63da044e0436e39cc291a0a9637712222 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Sun, 8 Aug 2021 14:40:00 -0700 Subject: [PATCH 244/429] Add tests for html escape functions --- .../frameworks/spring/webutil/Test.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/Test.java b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java index e2856917041..e37426ea4a6 100644 --- a/java/ql/test/library-tests/frameworks/spring/webutil/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java @@ -2579,6 +2579,48 @@ public class Test { out = WebUtils.parseMatrixVariables(in); sink(getMapValue(out)); // $hasTaintFlow } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscape;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscape(in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscape;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscape(in); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscapeDecimal;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscapeDecimal(in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscapeDecimal;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscapeDecimal(in); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscapeHex;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscapeHex(in, null); + sink(out); // $ hasTaintFlow + } + { + // "org.springframework.web.util;HtmlUtils;false;htmlEscapeHex;;;Argument[0];ReturnValue;taint" + String out = null; + String in = (String)source(); + out = HtmlUtils.htmlEscapeHex(in); + sink(out); // $ hasTaintFlow + } } From 4e69081c220a053940ab5ca3c3b67047faee6595 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Fri, 13 Aug 2021 20:52:27 +0200 Subject: [PATCH 245/429] Support multi-dimensional arrays --- .../StaticInitializationVectorQuery.qll | 10 ++-- .../CWE-1204/StaticInitializationVector.java | 48 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index f190153385e..40860075f88 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -3,13 +3,17 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.TaintTracking2 /** - * Holds if `array` is initialized only with constants, for example, - * `new byte[8]` or `new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }`. + * Holds if `array` is initialized only with constants. */ private predicate initializedWithConstants(ArrayCreationExpr array) { + // creating an array without an initializer, for example `new byte[8]` not exists(array.getInit()) or - forex(Expr element | element = array.getInit().getAChildExpr() | + // creating a multidimensional array with an initializer like `{ new byte[8], new byte[16] }` + array.getInit().getAnInit().getAChildExpr() instanceof IntegerLiteral + or + // creating an array wit an initializer like `new byte[] { 1, 2 }` + forex(Expr element | element = array.getInit().getAnInit() | element instanceof CompileTimeConstantExpr ) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java index 95a0d4b49f8..05ae7e4dd8b 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java @@ -50,6 +50,54 @@ public class StaticInitializationVector { return cipher.doFinal(); } + // BAD: AES-GCM with static IV from a multidimensional byte array + public byte[] encryptWithOneOfStaticIvs01(byte[] key, byte[] plaintext) throws Exception { + byte[][] staticIvs = new byte[][] { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } + }; + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, staticIvs[1]); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector + cipher.update(plaintext); + return cipher.doFinal(); + } + + // BAD: AES-GCM with static IV from a multidimensional byte array + public byte[] encryptWithOneOfStaticIvs02(byte[] key, byte[] plaintext) throws Exception { + byte[][] staticIvs = new byte[][] { + new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, + new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } + }; + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, staticIvs[1]); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector + cipher.update(plaintext); + return cipher.doFinal(); + } + + // BAD: AES-GCM with static IV from a multidimensional byte array + public byte[] encryptWithOneOfStaticZeroIvs(byte[] key, byte[] plaintext) throws Exception { + byte[][] ivs = new byte[][] { + new byte[8], + new byte[16] + }; + + GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivs[1]); + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + + Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $staticInitializationVector + cipher.update(plaintext); + return cipher.doFinal(); + } + // GOOD: AES-GCM with a random IV public byte[] encryptWithRandomIv(byte[] key, byte[] plaintext) throws Exception { byte[] iv = new byte[16]; From 11992404ec3bb368a4e3455d260532819a8defd4 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Sat, 14 Aug 2021 12:18:02 +0200 Subject: [PATCH 246/429] Be precise when checking for Cipher.ENCRYPT_MODE --- .../code/java/security/StaticInitializationVectorQuery.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index 40860075f88..66ebb38a521 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -102,7 +102,11 @@ private class EncryptionModeConfig extends TaintTracking2::Configuration { EncryptionModeConfig() { this = "EncryptionModeConfig" } override predicate isSource(DataFlow::Node source) { - source.asExpr().(VarAccess).getVariable().hasName("ENCRYPT_MODE") + source + .asExpr() + .(FieldRead) + .getField() + .hasQualifiedName("javax.crypto", "Cipher", "ENCRYPT_MODE") } override predicate isSink(DataFlow::Node sink) { From d218813320dd26113a9fee6f5c20aaec64d011bc Mon Sep 17 00:00:00 2001 From: Fosstars Date: Sat, 14 Aug 2021 13:09:14 +0200 Subject: [PATCH 247/429] Updated qldoc for ArrayUpdate --- .../code/java/security/StaticInitializationVectorQuery.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index 66ebb38a521..fe75c1df1fb 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -28,7 +28,12 @@ private class StaticByteArrayCreation extends ArrayCreationExpr { } } -/** Defines a sub-set of expressions that update an array. */ +/** + * Defines a sub-set of expressions that update either content of an array or an array reference. + * There sub-set covers only methods that are likely to set a non-static IV. + * For example, `java.util.Arrays.fill()` is not covered because it assigns the same value + * to each element of the array. + */ private class ArrayUpdate extends Expr { Expr array; From e2dc9753ac767b9110e33ea2d7d241a572410e71 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Sat, 14 Aug 2021 13:25:46 +0200 Subject: [PATCH 248/429] Covered copyOfRange() and clone() in ArrayUpdate --- .../code/java/security/StaticInitializationVectorQuery.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index fe75c1df1fb..128f40b8c88 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -51,7 +51,7 @@ private class ArrayUpdate extends Expr { ) or exists(StaticMethodAccess ma | - ma.getMethod().hasQualifiedName("java.util", "Arrays", "copyOf") and + ma.getMethod().hasQualifiedName("java.util", "Arrays", ["copyOf", "copyOfRange"]) and ma = this and ma = array ) @@ -66,6 +66,10 @@ private class ArrayUpdate extends Expr { m.hasQualifiedName("java.security", "SecureRandom", "nextBytes") or m.hasQualifiedName("java.util", "Random", "nextBytes") ) + or + exists(MethodAccess ma, Method m | m = ma.getMethod() | + m.getDeclaringType().hasName("byte[]") and m.hasName("clone") and ma = this and ma = array + ) } /** Returns the updated array. */ From 48872b4588ea58bfd100a002f8e3cf01e0af31c3 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 14 Aug 2021 19:47:09 +0200 Subject: [PATCH 249/429] Java: Improve Callable.getStringSignature() documentation --- java/ql/src/semmle/code/java/Member.qll | 29 ++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/java/ql/src/semmle/code/java/Member.qll b/java/ql/src/semmle/code/java/Member.qll index de8a6e2a11f..cd3be71bea7 100755 --- a/java/ql/src/semmle/code/java/Member.qll +++ b/java/ql/src/semmle/code/java/Member.qll @@ -183,14 +183,26 @@ class Callable extends StmtParent, Member, @callable { Type getParameterType(int n) { params(_, result, n, this, _) } /** - * Gets the signature of this callable, including its name and the types of all its parameters, - * identified by their simple (unqualified) names. + * Gets the signature of this callable, including its name and the types of all + * its parameters, identified by their simple (unqualified) names. + * + * The format of the string is ``, where `` is the result of + * the predicate `getName()` and `` is the result of `paramsString()`. + * For example, the method `void printf(java.lang.String, java.lang.Object...)` + * has the string signature `printf(String, Object[])`. * * Use `getSignature` to obtain a signature including fully qualified type names. */ string getStringSignature() { result = this.getName() + this.paramsString() } - /** Gets a parenthesized string containing all parameter types of this callable, separated by a comma. */ + /** + * Gets a parenthesized string containing all parameter types of this callable, + * separated by a comma and space. For the parameter types the unqualified string + * representation is used. If this callable has no parameters, the result is `()`. + * + * For example, the method `void printf(java.lang.String, java.lang.Object...)` + * has the params string `(String, Object[])`. + */ pragma[nomagic] string paramsString() { exists(int n | n = getNumberOfParameters() | @@ -210,7 +222,12 @@ class Callable extends StmtParent, Member, @callable { n > 0 and result = paramUpTo(n - 1) + ", " + getParameterType(n) } - /** Holds if this callable has the specified string signature. */ + /** + * Holds if this callable has the specified string signature. + * + * This predicate simply tests if `sig` is equal to the result of the + * `getStringSignature()` predicate. + */ predicate hasStringSignature(string sig) { sig = this.getStringSignature() } /** Gets an exception that occurs in the `throws` clause of this callable. */ @@ -250,8 +267,10 @@ class Callable extends StmtParent, Member, @callable { /** * Gets the signature of this callable, where all types in the signature have a fully-qualified name. + * The parameter types are only separated by a comma (without space). If this callable has + * no parameters, the callable name is followed by `()`. * - * For example, method `void m(String s)` has the signature `m(java.lang.String)`. + * For example, method `void m(String s, int i)` has the signature `m(java.lang.String,int)`. */ string getSignature() { constrs(this, _, result, _, _, _) or From fbac5891b874d1fa411f1e4e3a1f056529b9b241 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Sat, 14 Aug 2021 21:28:30 +0200 Subject: [PATCH 250/429] Fixed a typo in qldoc --- .../code/java/security/StaticInitializationVectorQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index 128f40b8c88..c5f43de99b6 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -30,7 +30,7 @@ private class StaticByteArrayCreation extends ArrayCreationExpr { /** * Defines a sub-set of expressions that update either content of an array or an array reference. - * There sub-set covers only methods that are likely to set a non-static IV. + * This sub-set covers only methods that are likely to set a non-static IV. * For example, `java.util.Arrays.fill()` is not covered because it assigns the same value * to each element of the array. */ From e962a7c77ce99e21c9a33308babfbbb7597b5c7e Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 16 Aug 2021 11:24:05 +0200 Subject: [PATCH 251/429] Update python/ql/src/semmle/python/RegexTreeView.qll Co-authored-by: yoff --- python/ql/src/semmle/python/RegexTreeView.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/python/ql/src/semmle/python/RegexTreeView.qll b/python/ql/src/semmle/python/RegexTreeView.qll index 5248f21922f..cc4c08c6364 100644 --- a/python/ql/src/semmle/python/RegexTreeView.qll +++ b/python/ql/src/semmle/python/RegexTreeView.qll @@ -839,9 +839,11 @@ class RegExpSubPattern extends RegExpZeroWidthMatch { /** Gets the lookahead term. */ RegExpTerm getOperand() { - result.getRegex() = re and - result.getStart() = start + 3 and - result.getEnd() = end - 1 + exists(int in_start, int in_end | re.groupContents(start, end, in_start, in_end) | + result.getRegex() = re and + result.getStart() = in_start and + result.getEnd() = in_end + ) } } From 4923bda0f384bd27c3e89c2e093cd21f8e1d0e64 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 16 Aug 2021 12:33:55 +0200 Subject: [PATCH 252/429] JS: Autoformat --- .../src/semmle/javascript/frameworks/Templating.qll | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 412fceee5aa..50a34a69ea5 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -317,16 +317,11 @@ module Templating { } pragma[nomagic] - private Folder getFolder() { - result = getFile().getParentContainer() - } + private Folder getFolder() { result = getFile().getParentContainer() } /** Gets the template file referenced by this node. */ final TemplateFile getTemplateFile() { - result = - this.getValue() - .(TemplateFileReferenceString) - .getTemplateFile(getFolder()) + result = this.getValue().(TemplateFileReferenceString).getTemplateFile(getFolder()) } } @@ -383,7 +378,8 @@ module Templating { DefaultTemplateReferenceString() { this = r.getValue().replaceAll("\\", "/") } - pragma[nomagic] // Stop optimizer from trying to share the 'getParentContainer' join + // Stop optimizer from trying to share the 'getParentContainer' join + pragma[nomagic] private Folder getFileReferenceFolder() { result = pragma[only_bind_out](r).getFile().getParentContainer() } From 74f372d547ceb2ef073adc0080bf880adb2ea01f Mon Sep 17 00:00:00 2001 From: ihsinme Date: Mon, 16 Aug 2021 14:11:28 +0300 Subject: [PATCH 253/429] Update UndefinedOrImplementationDefinedBehavior.ql --- .../CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql b/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql index a1dce27f81c..851d46abd46 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql @@ -163,4 +163,4 @@ where or eots.dangerousCrementChanges() ) -select eots, "This expression may have undefined behavior." +select eots, "This expression may have undefined behavior, because the order of evaluation is not specified." From c63dff639cce1cd5285c9b4e6c337e414bc6313e Mon Sep 17 00:00:00 2001 From: ihsinme Date: Mon, 16 Aug 2021 14:15:10 +0300 Subject: [PATCH 254/429] Update UndefinedOrImplementationDefinedBehavior.expected --- .../tests/UndefinedOrImplementationDefinedBehavior.expected | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-758/semmle/tests/UndefinedOrImplementationDefinedBehavior.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-758/semmle/tests/UndefinedOrImplementationDefinedBehavior.expected index 43ac03030dd..28585cefb0d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-758/semmle/tests/UndefinedOrImplementationDefinedBehavior.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-758/semmle/tests/UndefinedOrImplementationDefinedBehavior.expected @@ -1,3 +1,3 @@ -| test.c:13:10:13:21 | call to tmpFunction1 | This expression may have undefined behavior. | -| test.c:13:30:13:41 | call to tmpFunction2 | This expression may have undefined behavior. | -| test.c:16:15:16:20 | ... ++ | This expression may have undefined behavior. | +| test.c:13:10:13:21 | call to tmpFunction1 | This expression may have undefined behavior, because the order of evaluation is not specified. | +| test.c:13:30:13:41 | call to tmpFunction2 | This expression may have undefined behavior, because the order of evaluation is not specified. | +| test.c:16:15:16:20 | ... ++ | This expression may have undefined behavior, because the order of evaluation is not specified. | From 00475363376e8e0d8baf4e5741f98132d160ede0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 16 Aug 2021 13:21:30 +0200 Subject: [PATCH 255/429] JS: Add change note --- .../change-notes/2021-08-16-query-suffix-convention2.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 javascript/change-notes/2021-08-16-query-suffix-convention2.md diff --git a/javascript/change-notes/2021-08-16-query-suffix-convention2.md b/javascript/change-notes/2021-08-16-query-suffix-convention2.md new file mode 100644 index 00000000000..35e344e6303 --- /dev/null +++ b/javascript/change-notes/2021-08-16-query-suffix-convention2.md @@ -0,0 +1,6 @@ +lgtm,codescanning +* Some library files have been deprecated, which may affect custom queries. + Queries importing a data-flow configuration from `semmle.javascript.security.dataflow` should + ensure that the imported file ends with `Query`, and only import its top-level module. + For example, a query that imported `DomBasedXss::DomBasedXss` should from now on import `DomBasedXssQuery` + instead. From 6988912b72f9074fd44cfd53b7077ef0e0b33cd8 Mon Sep 17 00:00:00 2001 From: ihsinme Date: Mon, 16 Aug 2021 15:20:00 +0300 Subject: [PATCH 256/429] Update UndefinedOrImplementationDefinedBehavior.ql --- .../CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql b/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql index 851d46abd46..bafe3d13b84 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-758/UndefinedOrImplementationDefinedBehavior.ql @@ -163,4 +163,5 @@ where or eots.dangerousCrementChanges() ) -select eots, "This expression may have undefined behavior, because the order of evaluation is not specified." +select eots, + "This expression may have undefined behavior, because the order of evaluation is not specified." From 48c61fc4b4129638dcb173aa376b1604f3a5458c Mon Sep 17 00:00:00 2001 From: Joe Farebrother Date: Mon, 16 Aug 2021 13:50:54 +0100 Subject: [PATCH 257/429] Update models for `Cache.getAllPresent` and `LoadingCache.getAll` --- java/ql/src/semmle/code/java/frameworks/guava/Cache.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll index f995ce63fc2..3c271fba61d 100644 --- a/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll +++ b/java/ql/src/semmle/code/java/frameworks/guava/Cache.qll @@ -13,6 +13,9 @@ private class GuavaBaseCsv extends SummaryModelCsv { // lambda flow from Argument[1] not implemented "com.google.common.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value", "com.google.common.cache;Cache;true;getIfPresent;(Object);;MapValue of Argument[-1];ReturnValue;value", + // the true flow to MapKey of ReturnValue for getAllPresent is the intersection of the these inputs, but intersections cannot be modelled fully accurately. + "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;MapKey of Argument[-1];MapKey of ReturnValue;value", + "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value", "com.google.common.cache;Cache;true;getAllPresent;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value", "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[0];MapKey of Argument[-1];value", "com.google.common.cache;Cache;true;put;(Object,Object);;Argument[1];MapValue of Argument[-1];value", @@ -21,7 +24,8 @@ private class GuavaBaseCsv extends SummaryModelCsv { "com.google.common.cache;LoadingCache;true;get;(Object);;MapValue of Argument[-1];ReturnValue;value", "com.google.common.cache;LoadingCache;true;getUnchecked;(Object);;MapValue of Argument[-1];ReturnValue;value", "com.google.common.cache;LoadingCache;true;apply;(Object);;MapValue of Argument[-1];ReturnValue;value", - "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapKey of Argument[-1];MapKey of ReturnValue;value", // technically, an interestion between MapKey of Argument[-1] and Element of Argument[0]; but we don't model intersections. + "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of ReturnValue;value", + "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;Element of Argument[0];MapKey of Agument[-1];value", "com.google.common.cache;LoadingCache;true;getAll;(Iterable);;MapValue of Argument[-1];MapValue of ReturnValue;value" ] } From b23fabe8cbb67a3942697c482b7627d066a3e95c Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Mon, 16 Aug 2021 15:53:11 +0100 Subject: [PATCH 258/429] Fix errors from previous PR --- .../semmle/code/java/frameworks/apache/Collections.qll | 4 ++-- .../library-tests/frameworks/apache-collections/Test.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll index 92dfc534c56..bbda599b911 100644 --- a/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll +++ b/java/ql/src/semmle/code/java/frameworks/apache/Collections.qll @@ -5,7 +5,7 @@ private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.ExternalFlow /** - * The method `isNotEmpty` in either `org.apache.commons.collections.CollectionUtils` + * The method `isEmpty` in either `org.apache.commons.collections.CollectionUtils` * or `org.apache.commons.collections4.CollectionUtils`. */ class MethodApacheCollectionsIsEmpty extends Method { @@ -146,7 +146,7 @@ private class ApacheKeyValueModel extends SummaryModelCsv { [ ".keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[0];MapKey of Argument[-1];value", ".keyvalue;AbstractKeyValue;true;AbstractKeyValue;;;Argument[1];MapValue of Argument[-1];value", - ".keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value", + ".keyvalue;AbstractKeyValue;true;setKey;;;MapKey of Argument[-1];ReturnValue;value", ".keyvalue;AbstractKeyValue;true;setKey;;;Argument[0];MapKey of Argument[-1];value", ".keyvalue;AbstractKeyValue;true;setValue;;;MapValue of Argument[-1];ReturnValue;value", ".keyvalue;AbstractKeyValue;true;setValue;;;Argument[0];MapValue of Argument[-1];value", diff --git a/java/ql/test/library-tests/frameworks/apache-collections/Test.java b/java/ql/test/library-tests/frameworks/apache-collections/Test.java index bed2384a73f..6884ff8b055 100644 --- a/java/ql/test/library-tests/frameworks/apache-collections/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-collections/Test.java @@ -225,16 +225,16 @@ public class Test { sink(getMapKey(out)); // $ hasValueFlow } { - // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" + // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - DefaultKeyValue in = newDKVWithMapValue((String)source()); + DefaultKeyValue in = newDKVWithMapKey((String)source()); out = in.setKey(null); sink(out); // $ hasValueFlow } { - // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapValue of Argument[-1];ReturnValue;value" + // "org.apache.commons.collections4.keyvalue;AbstractKeyValue;true;setKey;;;MapKey of Argument[-1];ReturnValue;value" Object out = null; - MyAbstractKeyValue in = newMAKVWithMapValue((String)source()); + MyAbstractKeyValue in = newMAKVWithMapKey((String)source()); out = in.mySetKey(null); sink(out); // $ hasValueFlow } From ff3f85be49171d157f098a7464e6a013d1fdd70a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 16 Aug 2021 18:09:40 +0100 Subject: [PATCH 259/429] Autoformat --- java/ql/src/semmle/code/java/security/XSS.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/semmle/code/java/security/XSS.qll b/java/ql/src/semmle/code/java/security/XSS.qll index 89694c8a904..2ebcff73998 100644 --- a/java/ql/src/semmle/code/java/security/XSS.qll +++ b/java/ql/src/semmle/code/java/security/XSS.qll @@ -93,8 +93,8 @@ private class DefaultXssSink extends XssSink { /** A default sanitizer that considers numeric and boolean typed data safe for writing to output. */ private class DefaultXSSSanitizer extends XssSanitizer { DefaultXSSSanitizer() { - this.getType() instanceof NumericType or this.getType() instanceof BooleanType - or + this.getType() instanceof NumericType or + this.getType() instanceof BooleanType or // Match `org.springframework.web.util.HtmlUtils.htmlEscape` and possibly other methods like it. this.asExpr().(MethodAccess).getMethod().getName().regexpMatch("(?i)html_?escape.*") } From cc2a267b07256c39c6b9526711f54fde1fa98488 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 16 Aug 2021 22:35:57 +0200 Subject: [PATCH 260/429] recognize array elements from JQuery objects as DOM values --- javascript/ql/src/semmle/javascript/DOM.qll | 7 +++++++ .../CWE-079/XssThroughDom/XssThroughDom.expected | 10 ++++++++++ .../Security/CWE-079/XssThroughDom/xss-through-dom.js | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/src/semmle/javascript/DOM.qll index f61c09dd9d8..4956502d7d2 100644 --- a/javascript/ql/src/semmle/javascript/DOM.qll +++ b/javascript/ql/src/semmle/javascript/DOM.qll @@ -384,6 +384,13 @@ module DOM { this = eachCall.getABoundCallbackParameter(0, 1) ) or + // A read of an array-element from a JQuery object. E.g. `$("#foo")[0]` + exists(DataFlow::PropRead read | + read = this and read = JQuery::objectRef().getAPropertyRead() + | + unique(InferredType t | t = read.getPropertyNameExpr().analyze().getAType()) = TTNumber() + ) + or // A receiver node of an event handler on a DOM node exists(DataFlow::SourceNode domNode, DataFlow::FunctionNode eventHandler | // NOTE: we do not use `getABoundFunctionValue()`, since bound functions tend to have 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 b726a851f09..5d088481711 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 @@ -112,6 +112,12 @@ nodes | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | | xss-through-dom.js:87:36:87:39 | text | +| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | +| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | +| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | +| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | +| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | +| xss-through-dom.js:96:17:96:47 | $("#foo ... ].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 | @@ -178,6 +184,8 @@ edges | xss-through-dom.js:86:33:86:36 | text | xss-through-dom.js:86:16:86:37 | anser.a ... l(text) | | xss-through-dom.js:87:36:87:39 | text | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | | xss-through-dom.js:87:36:87:39 | text | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | +| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | +| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].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 | @@ -209,3 +217,5 @@ edges | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | DOM text | | xss-through-dom.js:86:16:86:37 | anser.a ... l(text) | xss-through-dom.js:84:15:84:30 | $("text").text() | xss-through-dom.js:86:16:86:37 | anser.a ... l(text) | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:84:15:84:30 | $("text").text() | DOM text | | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | xss-through-dom.js:84:15:84:30 | $("text").text() | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:84:15:84:30 | $("text").text() | DOM text | +| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | DOM text | +| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:96:17:96:47 | $("#foo ... ].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 656f233ca9e..d7f6d6a8208 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 @@ -89,4 +89,10 @@ $("section h1").each(function(){ $("nav ul").append("Section"); // OK }); + + $("#id").html($("#foo").find(".bla")[0].value); // NOT OK. + + for (var i = 0; i < foo.length; i++) { + $("#id").html($("#foo").find(".bla")[i].value); // NOT OK. + } })(); \ No newline at end of file From e566fb9c5a01bb678bf25825562aebc740952aed Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Mon, 16 Aug 2021 17:28:14 -0700 Subject: [PATCH 261/429] Packaging: Update suite-helpers qlpack Uses new style naming scheme. --- .codeqlmanifest.json | 1 + cpp/ql/src/codeql-suites/cpp-code-scanning.qls | 2 +- cpp/ql/src/codeql-suites/cpp-lgtm-full.qls | 4 ++-- cpp/ql/src/codeql-suites/cpp-lgtm.qls | 2 +- cpp/ql/src/codeql-suites/cpp-security-and-quality.qls | 2 +- cpp/ql/src/codeql-suites/cpp-security-extended.qls | 2 +- csharp/ql/src/codeql-suites/csharp-code-scanning.qls | 2 +- csharp/ql/src/codeql-suites/csharp-lgtm-full.qls | 2 +- csharp/ql/src/codeql-suites/csharp-lgtm.qls | 2 +- csharp/ql/src/codeql-suites/csharp-security-and-quality.qls | 2 +- csharp/ql/src/codeql-suites/csharp-security-extended.qls | 2 +- java/ql/src/codeql-suites/java-code-scanning.qls | 2 +- java/ql/src/codeql-suites/java-lgtm-full.qls | 2 +- java/ql/src/codeql-suites/java-lgtm.qls | 2 +- java/ql/src/codeql-suites/java-security-and-quality.qls | 2 +- java/ql/src/codeql-suites/java-security-extended.qls | 2 +- javascript/ql/src/codeql-suites/javascript-code-scanning.qls | 2 +- javascript/ql/src/codeql-suites/javascript-lgtm-full.qls | 2 +- javascript/ql/src/codeql-suites/javascript-lgtm.qls | 2 +- .../ql/src/codeql-suites/javascript-security-and-quality.qls | 2 +- .../ql/src/codeql-suites/javascript-security-extended.qls | 2 +- misc/suite-helpers/qlpack.lock.yml | 4 ++++ misc/suite-helpers/qlpack.yml | 5 +++-- python/ql/src/codeql-suites/python-code-scanning.qls | 2 +- python/ql/src/codeql-suites/python-lgtm-full.qls | 2 +- python/ql/src/codeql-suites/python-lgtm.qls | 2 +- python/ql/src/codeql-suites/python-security-and-quality.qls | 2 +- python/ql/src/codeql-suites/python-security-extended.qls | 2 +- 28 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 misc/suite-helpers/qlpack.lock.yml diff --git a/.codeqlmanifest.json b/.codeqlmanifest.json index 81d370e793d..4efe12f6d2b 100644 --- a/.codeqlmanifest.json +++ b/.codeqlmanifest.json @@ -1,4 +1,5 @@ { "provide": [ "*/ql/src/qlpack.yml", + "*/ql/lib/qlpack.yml", "*/ql/test/qlpack.yml", "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml", "*/ql/examples/qlpack.yml", diff --git a/cpp/ql/src/codeql-suites/cpp-code-scanning.qls b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls index f811010a26a..4a8a85cae42 100644 --- a/cpp/ql/src/codeql-suites/cpp-code-scanning.qls +++ b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls @@ -1,6 +1,6 @@ - description: Standard Code Scanning queries for C and C++ - qlpack: codeql-cpp - apply: code-scanning-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers - apply: codeql-suites/exclude-slow-queries.yml from: codeql-cpp diff --git a/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls b/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls index b6775597c30..11416fccb7c 100644 --- a/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls +++ b/cpp/ql/src/codeql-suites/cpp-lgtm-full.qls @@ -1,9 +1,9 @@ - description: Standard LGTM queries for C/C++, including ones not displayed by default - qlpack: codeql-cpp - apply: lgtm-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers - apply: codeql-suites/exclude-slow-queries.yml - from: codeql-cpp + from: codeql-cpp # These are only for IDE use. - exclude: tags contain: diff --git a/cpp/ql/src/codeql-suites/cpp-lgtm.qls b/cpp/ql/src/codeql-suites/cpp-lgtm.qls index fe06e19b7fa..fe88b035276 100644 --- a/cpp/ql/src/codeql-suites/cpp-lgtm.qls +++ b/cpp/ql/src/codeql-suites/cpp-lgtm.qls @@ -1,4 +1,4 @@ - description: Standard LGTM queries for C/C++ - apply: codeql-suites/cpp-lgtm-full.qls - apply: lgtm-displayed-only.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/cpp/ql/src/codeql-suites/cpp-security-and-quality.qls b/cpp/ql/src/codeql-suites/cpp-security-and-quality.qls index 297f46bc752..f212afedba6 100644 --- a/cpp/ql/src/codeql-suites/cpp-security-and-quality.qls +++ b/cpp/ql/src/codeql-suites/cpp-security-and-quality.qls @@ -1,6 +1,6 @@ - description: Security-and-quality queries for C and C++ - qlpack: codeql-cpp - apply: security-and-quality-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers - apply: codeql-suites/exclude-slow-queries.yml from: codeql-cpp diff --git a/cpp/ql/src/codeql-suites/cpp-security-extended.qls b/cpp/ql/src/codeql-suites/cpp-security-extended.qls index fa69559add0..26063f088d2 100644 --- a/cpp/ql/src/codeql-suites/cpp-security-extended.qls +++ b/cpp/ql/src/codeql-suites/cpp-security-extended.qls @@ -1,6 +1,6 @@ - description: Security-extended queries for C and C++ - qlpack: codeql-cpp - apply: security-extended-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers - apply: codeql-suites/exclude-slow-queries.yml from: codeql-cpp diff --git a/csharp/ql/src/codeql-suites/csharp-code-scanning.qls b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls index 3646204da7d..36495d0562e 100644 --- a/csharp/ql/src/codeql-suites/csharp-code-scanning.qls +++ b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for C# - qlpack: codeql-csharp - apply: code-scanning-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls b/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls index 8ba077663d0..14bf575bd70 100644 --- a/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls +++ b/csharp/ql/src/codeql-suites/csharp-lgtm-full.qls @@ -1,7 +1,7 @@ - description: Standard LGTM queries for C#, including ones not displayed by default - qlpack: codeql-csharp - apply: lgtm-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers # These are only for IDE use. - exclude: tags contain: diff --git a/csharp/ql/src/codeql-suites/csharp-lgtm.qls b/csharp/ql/src/codeql-suites/csharp-lgtm.qls index 1e8a9a2fb7c..d6f9a355b69 100644 --- a/csharp/ql/src/codeql-suites/csharp-lgtm.qls +++ b/csharp/ql/src/codeql-suites/csharp-lgtm.qls @@ -1,4 +1,4 @@ - description: Standard LGTM queries for C# - apply: codeql-suites/csharp-lgtm-full.qls - apply: lgtm-displayed-only.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/csharp/ql/src/codeql-suites/csharp-security-and-quality.qls b/csharp/ql/src/codeql-suites/csharp-security-and-quality.qls index 20ead656db0..f4da662da2b 100644 --- a/csharp/ql/src/codeql-suites/csharp-security-and-quality.qls +++ b/csharp/ql/src/codeql-suites/csharp-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for C# - qlpack: codeql-csharp - apply: security-and-quality-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/csharp/ql/src/codeql-suites/csharp-security-extended.qls b/csharp/ql/src/codeql-suites/csharp-security-extended.qls index b74ffa9c2e0..a8cc8906307 100644 --- a/csharp/ql/src/codeql-suites/csharp-security-extended.qls +++ b/csharp/ql/src/codeql-suites/csharp-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for C# - qlpack: codeql-csharp - apply: security-extended-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/java/ql/src/codeql-suites/java-code-scanning.qls b/java/ql/src/codeql-suites/java-code-scanning.qls index 7dc29ab8049..e63526f5626 100644 --- a/java/ql/src/codeql-suites/java-code-scanning.qls +++ b/java/ql/src/codeql-suites/java-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for Java - qlpack: codeql-java - apply: code-scanning-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/java/ql/src/codeql-suites/java-lgtm-full.qls b/java/ql/src/codeql-suites/java-lgtm-full.qls index 542174d9101..3fc3a23e05e 100644 --- a/java/ql/src/codeql-suites/java-lgtm-full.qls +++ b/java/ql/src/codeql-suites/java-lgtm-full.qls @@ -1,7 +1,7 @@ - description: Standard LGTM queries for Java, including ones not displayed by default - qlpack: codeql-java - apply: lgtm-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers # These are only for IDE use. - exclude: tags contain: diff --git a/java/ql/src/codeql-suites/java-lgtm.qls b/java/ql/src/codeql-suites/java-lgtm.qls index d0733ee7408..8b8f8d973c7 100644 --- a/java/ql/src/codeql-suites/java-lgtm.qls +++ b/java/ql/src/codeql-suites/java-lgtm.qls @@ -1,4 +1,4 @@ - description: Standard LGTM queries for Java - apply: codeql-suites/java-lgtm-full.qls - apply: lgtm-displayed-only.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/java/ql/src/codeql-suites/java-security-and-quality.qls b/java/ql/src/codeql-suites/java-security-and-quality.qls index 1709789eb75..356e1259830 100644 --- a/java/ql/src/codeql-suites/java-security-and-quality.qls +++ b/java/ql/src/codeql-suites/java-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for Java - qlpack: codeql-java - apply: security-and-quality-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/java/ql/src/codeql-suites/java-security-extended.qls b/java/ql/src/codeql-suites/java-security-extended.qls index df10997bb38..af306a9e06e 100644 --- a/java/ql/src/codeql-suites/java-security-extended.qls +++ b/java/ql/src/codeql-suites/java-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for Java - qlpack: codeql-java - apply: security-extended-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls index f87a55157a2..8ec0309619d 100644 --- a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls +++ b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for JavaScript - qlpack: codeql-javascript - apply: code-scanning-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls index 98de43e41a9..b4336c666ae 100644 --- a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls +++ b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls @@ -1,7 +1,7 @@ - description: Standard LGTM queries for JavaScript, including ones not displayed by default - qlpack: codeql-javascript - apply: lgtm-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers # These are only for IDE use. - exclude: tags contain: diff --git a/javascript/ql/src/codeql-suites/javascript-lgtm.qls b/javascript/ql/src/codeql-suites/javascript-lgtm.qls index 3ff42dfa9ac..4443beb1988 100644 --- a/javascript/ql/src/codeql-suites/javascript-lgtm.qls +++ b/javascript/ql/src/codeql-suites/javascript-lgtm.qls @@ -1,4 +1,4 @@ - description: Standard LGTM queries for JavaScript - apply: codeql-suites/javascript-lgtm-full.qls - apply: lgtm-displayed-only.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls b/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls index d20b67f9699..4d64a6e7a52 100644 --- a/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls +++ b/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for JavaScript - qlpack: codeql-javascript - apply: security-and-quality-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-security-extended.qls b/javascript/ql/src/codeql-suites/javascript-security-extended.qls index 734a6335916..ea78d5a0f05 100644 --- a/javascript/ql/src/codeql-suites/javascript-security-extended.qls +++ b/javascript/ql/src/codeql-suites/javascript-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for JavaScript - qlpack: codeql-javascript - apply: security-extended-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/misc/suite-helpers/qlpack.lock.yml b/misc/suite-helpers/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/misc/suite-helpers/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index fd6c1fdf290..ca0a6732f5a 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,2 +1,3 @@ -name: codeql-suite-helpers -version: 0.0.0 +name: codeql/suite-helpers +version: 0.0.2 +library: true diff --git a/python/ql/src/codeql-suites/python-code-scanning.qls b/python/ql/src/codeql-suites/python-code-scanning.qls index f9f9a5425b6..e356f34c26e 100644 --- a/python/ql/src/codeql-suites/python-code-scanning.qls +++ b/python/ql/src/codeql-suites/python-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for Python - qlpack: codeql-python - apply: code-scanning-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/python/ql/src/codeql-suites/python-lgtm-full.qls b/python/ql/src/codeql-suites/python-lgtm-full.qls index f13d4607b66..42a9b332211 100644 --- a/python/ql/src/codeql-suites/python-lgtm-full.qls +++ b/python/ql/src/codeql-suites/python-lgtm-full.qls @@ -1,7 +1,7 @@ - description: Standard LGTM queries for Python, including ones not displayed by default - qlpack: codeql-python - apply: lgtm-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers # These are only for IDE use. - exclude: tags contain: diff --git a/python/ql/src/codeql-suites/python-lgtm.qls b/python/ql/src/codeql-suites/python-lgtm.qls index 61ba43df811..65add0f4d5d 100644 --- a/python/ql/src/codeql-suites/python-lgtm.qls +++ b/python/ql/src/codeql-suites/python-lgtm.qls @@ -1,4 +1,4 @@ - description: Standard LGTM queries for Python - apply: codeql-suites/python-lgtm-full.qls - apply: lgtm-displayed-only.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/python/ql/src/codeql-suites/python-security-and-quality.qls b/python/ql/src/codeql-suites/python-security-and-quality.qls index c4e5d4fc8c0..4971989fd5c 100644 --- a/python/ql/src/codeql-suites/python-security-and-quality.qls +++ b/python/ql/src/codeql-suites/python-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for Python - qlpack: codeql-python - apply: security-and-quality-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers diff --git a/python/ql/src/codeql-suites/python-security-extended.qls b/python/ql/src/codeql-suites/python-security-extended.qls index e0e99533b8c..068ada84fcd 100644 --- a/python/ql/src/codeql-suites/python-security-extended.qls +++ b/python/ql/src/codeql-suites/python-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for Python - qlpack: codeql-python - apply: security-extended-selectors.yml - from: codeql-suite-helpers + from: codeql/suite-helpers From 390e48fdd20dbf525bbed13b62623d510f147ed4 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Tue, 17 Aug 2021 02:17:36 -0700 Subject: [PATCH 262/429] Remove more redundant models --- .../src/semmle/code/java/frameworks/spring/SpringWebUtil.qll | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll index f753464ab26..89def3a3e61 100644 --- a/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll +++ b/java/ql/src/semmle/code/java/frameworks/spring/SpringWebUtil.qll @@ -63,9 +63,6 @@ private class FlowSummaries extends SummaryModelCsv { "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentInputStream;;;Argument[-1];ReturnValue;taint", "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[-1];taint", "org.springframework.web.util;DefaultUriBuilderFactory;false;builder;;;Argument[-1];ReturnValue;taint", - "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[-1..0];ReturnValue;taint", - "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint", - "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint", "org.springframework.web.util;DefaultUriBuilderFactory;false;getDefaultUriVariables;;;Argument[-1];MapValue of ReturnValue;taint", "org.springframework.web.util;DefaultUriBuilderFactory;false;setDefaultUriVariables;;;MapValue of Argument[0];Argument[-1];taint", "org.springframework.web.util;DefaultUriBuilderFactory;false;uriString;;;Argument[-1];ReturnValue;taint", From 15d483d56ca93b632779fd63c276c46aa0a6156a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 17 Aug 2021 12:03:40 +0200 Subject: [PATCH 263/429] Python: Use TypeTrackingNode in new PEP249 modeling --- .../semmle/python/frameworks/internal/PEP249Impl.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll index 254dcb98cb6..65960d50392 100644 --- a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll @@ -61,7 +61,7 @@ module PEP249 { } /** Gets a reference to a database connection (following PEP 249). */ - private DataFlow::LocalSourceNode instance(DataFlow::TypeTracker t) { + private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) { t.start() and result instanceof InstanceSource or @@ -94,7 +94,7 @@ module PEP249 { abstract class InstanceSource extends DataFlow::LocalSourceNode { } /** Gets a reference to a database cursor. */ - private DataFlow::LocalSourceNode instance(DataFlow::TypeTracker t) { + private DataFlow::TypeTrackingNode instance(DataFlow::TypeTracker t) { t.start() and result instanceof InstanceSource or @@ -105,7 +105,7 @@ module PEP249 { DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) } /** Gets a reference to the `cursor` method on a database connection. */ - private DataFlow::LocalSourceNode methodRef(DataFlow::TypeTracker t) { + private DataFlow::TypeTrackingNode methodRef(DataFlow::TypeTracker t) { t.startInAttr("cursor") and result = Connection::instance() or @@ -121,7 +121,7 @@ module PEP249 { } /** Gets a reference to a result of calling the `cursor` method on a database connection. */ - private DataFlow::LocalSourceNode methodResult(DataFlow::TypeTracker t) { + private DataFlow::TypeTrackingNode methodResult(DataFlow::TypeTracker t) { t.start() and result.asCfgNode().(CallNode).getFunction() = methodRef().asCfgNode() or @@ -146,7 +146,7 @@ module PEP249 { * * See https://www.python.org/dev/peps/pep-0249/#id15. */ - private DataFlow::LocalSourceNode execute(DataFlow::TypeTracker t) { + private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) { t.startInAttr("execute") and result in [Cursor::instance(), Connection::instance()] or From 59f0a41665dee0bda1d174fbd180d8d6d8a00679 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 18 May 2021 21:51:28 +0200 Subject: [PATCH 264/429] support more regular expressions in js/incomplete-multi-character-sanitization --- .../IncompleteMultiCharacterSanitization.ql | 65 ++++++++++++++----- .../security/performance/ReDoSUtil.qll | 2 +- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index 1cd23ea4432..e38d9f496f8 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -56,31 +56,62 @@ DangerousPrefix getADangerousMatchedPrefix(EmptyReplaceRegExpTerm t) { not exists(EmptyReplaceRegExpTerm pred | pred = t.getPredecessor+() and not pred.isNullable()) } +private import semmle.javascript.security.performance.ReDoSUtil as ReDoSUtil + +/** + * Gets a char from a dangerous prefix that is matched by `t`. + */ +pragma[noinline] +DangerousPrefixSubstring getADangerousMatchedChar(EmptyReplaceRegExpTerm t) { + t.isNullable() and result = "" + or + t.getAMatchedString() = result + or + ReDoSUtil::getCanonicalCharClass(t).(ReDoSUtil::CharacterClass).matches(result) + or + t instanceof RegExpDot and + result.length() = 1 + or + ( + t instanceof RegExpOpt or + t instanceof RegExpStar or + t instanceof RegExpPlus or + t instanceof RegExpGroup or + t instanceof RegExpAlt + ) and + result = getADangerousMatchedChar(t.getAChild()) +} + /** * 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 - 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 + result = getADangerousMatchedChar(t) + getADangerousMatchedPrefixSubstring(t.getSuccessor()) + or + result = getADangerousMatchedChar(t) + or + // loop around for repetitions (only considering alphanumeric characters in the repetition) + exists(RepetitionMatcher repetition | t = repetition | + result = getADangerousMatchedPrefixSubstring(repetition) + repetition.getAChar() ) } +class RepetitionMatcher extends EmptyReplaceRegExpTerm { + string char; + + pragma[noinline] + RepetitionMatcher() { + (this instanceof RegExpPlus or this instanceof RegExpStar) and + char = getADangerousMatchedChar(this.getAChild()) and + char.regexpMatch("\\w") + } + + pragma[noinline] + string getAChar() { result = char } +} + /** * Holds if `t` may match the dangerous `prefix` and some suffix, indicating intent to prevent a vulnerablity of kind `kind`. */ @@ -151,7 +182,7 @@ where // 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 + prefix = max(string m | matchesDangerousPrefix(dangerous, m, kind) | m order by m.length(), m) and // only warn once per kind not exists(EmptyReplaceRegExpTerm other | other = dangerous.getAChild+() or other = dangerous.getPredecessor+() diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll index 38eede15e8a..b752b952a88 100644 --- a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll @@ -251,7 +251,7 @@ class InputSymbol extends TInputSymbol { /** * An abstract input symbol that represents a character class. */ -abstract private class CharacterClass extends InputSymbol { +abstract class CharacterClass extends InputSymbol { /** * Gets a character that is relevant for intersection-tests involving this * character class. From 5d4c434d34cd179949da5bfcf230cf0861222028 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 10 Aug 2021 19:58:56 +0200 Subject: [PATCH 265/429] restrict char class matches to alpha-numeric chars --- .../Security/CWE-116/IncompleteMultiCharacterSanitization.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql index e38d9f496f8..b07672a931c 100644 --- a/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql +++ b/javascript/ql/src/Security/CWE-116/IncompleteMultiCharacterSanitization.ql @@ -67,7 +67,8 @@ DangerousPrefixSubstring getADangerousMatchedChar(EmptyReplaceRegExpTerm t) { or t.getAMatchedString() = result or - ReDoSUtil::getCanonicalCharClass(t).(ReDoSUtil::CharacterClass).matches(result) + ReDoSUtil::getCanonicalCharClass(t).(ReDoSUtil::CharacterClass).matches(result) and + result.regexpMatch("\\w") or t instanceof RegExpDot and result.length() = 1 From 6d06550f7dc72c12dfe13c8313ab93e1752c3704 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 10 Aug 2021 19:58:28 +0200 Subject: [PATCH 266/429] update expected output --- .../IncompleteMultiCharacterSanitization.expected | 5 +++-- .../tst-multi-character-sanitization.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) 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 172baa9c1c1..239cd387254 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,7 +1,7 @@ -| 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 | < | /gi, ""); // NOT OK content.replace(/<(script).*\/script>/gi, ""); // NOT OK - content.replace(/.+<(script).*\/script>/gi, ""); // OK + content.replace(/.+<(script).*\/script>/gi, ""); // NOT OK content.replace(/.*<(script).*\/script>/gi, ""); // NOT OK }); From 9c2d83e82b3a777de5aacb1b47476b2343f8b5a2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 10 Aug 2021 19:59:06 +0200 Subject: [PATCH 267/429] add tests --- .../IncompleteMultiCharacterSanitization.expected | 4 ++++ .../tst-multi-character-sanitization.js | 7 +++++++ 2 files changed, 11 insertions(+) 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 239cd387254..4cfa0c0ac66 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 @@ -33,3 +33,7 @@ | 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 | < | + \ No newline at end of file diff --git a/javascript/extractor/tests/generatedcode/output/trap/test.html.trap b/javascript/extractor/tests/generatedcode/output/trap/test.html.trap index ec2f280c5e1..1cb0292dd84 100644 --- a/javascript/extractor/tests/generatedcode/output/trap/test.html.trap +++ b/javascript/extractor/tests/generatedcode/output/trap/test.html.trap @@ -238,168 +238,168 @@ successor(#20051,#20056) successor(#20070,#20049) toplevel_parent_xml_node(#20002,#20001) #20072=* -xmlChars(#20072," -",#10000,0,0,#10000) -#20073=@"loc,{#10000},1,16,1,16" -locations_default(#20073,#10000,1,16,1,16) -xmllocations(#20072,#20073) -#20074=* -xmlElements(#20074,"html",#10000,1,#10000) -#20075=@"loc,{#10000},2,1,14,7" -locations_default(#20075,#10000,2,1,14,7) -xmllocations(#20074,#20075) +#20073=* +template_placeholder_tag_info(#20072,#20073,"{{ attr1 }}") +#20074=@"loc,{#10000},13,14,13,24" +locations_default(#20074,#10000,13,14,13,24) +hasLocation(#20072,#20074) +scopes(#20000,0) +#20075=@"script;{#10000},13,16" #20076=* -xmlChars(#20076," - ",#20074,0,0,#10000) -#20077=@"loc,{#10000},2,7,3,2" -locations_default(#20077,#10000,2,7,3,2) -xmllocations(#20076,#20077) +lines(#20076,#20075," attr1 ","") +#20077=@"loc,{#10000},13,16,13,22" +locations_default(#20077,#10000,13,16,13,22) +hasLocation(#20076,#20077) +indentation(#10000,13," ",1) +numlines(#20075,1,1,0) #20078=* -xmlChars(#20078," -",#20074,2,0,#10000) -#20079=@"loc,{#10000},13,10,13,10" -locations_default(#20079,#10000,13,10,13,10) -xmllocations(#20078,#20079) +tokeninfo(#20078,6,#20075,0,"attr1") +#20079=@"loc,{#10000},13,17,13,21" +locations_default(#20079,#10000,13,17,13,21) +hasLocation(#20078,#20079) #20080=* -xmlElements(#20080,"body",#20074,1,#10000) -#20081=@"loc,{#10000},3,3,13,9" -locations_default(#20081,#10000,3,3,13,9) -xmllocations(#20080,#20081) -#20082=* -xmlChars(#20082," - ",#20080,0,0,#10000) -#20083=@"loc,{#10000},3,9,4,4" -locations_default(#20083,#10000,3,9,4,4) -xmllocations(#20082,#20083) +tokeninfo(#20080,0,#20075,1,"") +#20081=@"loc,{#10000},13,23,13,22" +locations_default(#20081,#10000,13,23,13,22) +hasLocation(#20080,#20081) +toplevels(#20075,4) +hasLocation(#20075,#20077) +#20082=@"module;{#10000},13,16" +scopes(#20082,3) +scopenodes(#20075,#20082) +scopenesting(#20082,#20000) +is_module(#20075) +#20083=* +stmts(#20083,2,#20075,0,"attr1") +hasLocation(#20083,#20079) +stmt_containers(#20083,#20075) #20084=* -template_placeholder_tag_info(#20084,#20080,"{{{subtitle_html}}}") -#20085=@"loc,{#10000},5,5,5,23" -locations_default(#20085,#10000,5,5,5,23) -hasLocation(#20084,#20085) -scopes(#20000,0) -#20086=@"script;{#10000},5,8" -#20087=* -lines(#20087,#20086,"subtitle_html","") -#20088=@"loc,{#10000},5,8,5,20" -locations_default(#20088,#10000,5,8,5,20) -hasLocation(#20087,#20088) -numlines(#20086,1,1,0) +exprs(#20084,79,#20083,0,"attr1") +hasLocation(#20084,#20079) +enclosing_stmt(#20084,#20083) +expr_containers(#20084,#20075) +literals("attr1","attr1",#20084) +#20085=@"var;{attr1};{#20082}" +variables(#20085,"attr1",#20082) +bind(#20084,#20085) +#20086=* +entry_cfg_node(#20086,#20075) +#20087=@"loc,{#10000},13,16,13,15" +locations_default(#20087,#10000,13,16,13,15) +hasLocation(#20086,#20087) +#20088=* +exit_cfg_node(#20088,#20075) +hasLocation(#20088,#20081) +successor(#20083,#20084) +successor(#20084,#20088) +successor(#20086,#20083) +toplevel_parent_xml_node(#20075,#20072) #20089=* -tokeninfo(#20089,6,#20086,0,"subtitle_html") -hasLocation(#20089,#20088) #20090=* -tokeninfo(#20090,0,#20086,1,"") -#20091=@"loc,{#10000},5,21,5,20" -locations_default(#20091,#10000,5,21,5,20) -hasLocation(#20090,#20091) -toplevels(#20086,4) -hasLocation(#20086,#20088) -#20092=@"module;{#10000},5,8" -scopes(#20092,3) -scopenodes(#20086,#20092) -scopenesting(#20092,#20000) -is_module(#20086) -#20093=* -stmts(#20093,2,#20086,0,"subtitle_html") -hasLocation(#20093,#20088) -stmt_containers(#20093,#20086) -#20094=* -exprs(#20094,79,#20093,0,"subtitle_html") -hasLocation(#20094,#20088) -enclosing_stmt(#20094,#20093) -expr_containers(#20094,#20086) -literals("subtitle_html","subtitle_html",#20094) -#20095=@"var;{subtitle_html};{#20092}" -variables(#20095,"subtitle_html",#20092) -bind(#20094,#20095) -#20096=* -entry_cfg_node(#20096,#20086) -#20097=@"loc,{#10000},5,8,5,7" -locations_default(#20097,#10000,5,8,5,7) -hasLocation(#20096,#20097) -#20098=* -exit_cfg_node(#20098,#20086) -hasLocation(#20098,#20091) -successor(#20093,#20094) -successor(#20094,#20098) -successor(#20096,#20093) -toplevel_parent_xml_node(#20086,#20084) -#20099=* -xmlChars(#20099," - {{{subtitle_html}}} - ",#20080,2,0,#10000) -#20100=@"loc,{#10000},4,23,6,4" -locations_default(#20100,#10000,4,23,6,4) -xmllocations(#20099,#20100) -#20101=* -xmlChars(#20101," - ",#20080,4,0,#10000) -#20102=@"loc,{#10000},6,28,7,4" -locations_default(#20102,#10000,6,28,7,4) -xmllocations(#20101,#20102) -#20103=* -xmlChars(#20103," - ",#20080,6,0,#10000) -#20104=@"loc,{#10000},7,25,8,4" -locations_default(#20104,#10000,7,25,8,4) -xmllocations(#20103,#20104) -#20105=* -xmlChars(#20105," - ",#20080,8,0,#10000) -#20106=@"loc,{#10000},12,14,13,2" -locations_default(#20106,#10000,12,14,13,2) -xmllocations(#20105,#20106) -xmlElements(#20001,"script",#20080,7,#10000) -#20107=@"loc,{#10000},8,5,12,13" -locations_default(#20107,#10000,8,5,12,13) -xmllocations(#20001,#20107) -#20108=* -template_placeholder_tag_info(#20108,#20001,"{{{ user_data1 }}}") -locations_default(#20055,#10000,9,19,9,36) -hasLocation(#20108,#20055) +template_placeholder_tag_info(#20089,#20090,"{{{ attr2 }}}") +#20091=@"loc,{#10000},13,34,13,46" +locations_default(#20091,#10000,13,34,13,46) +hasLocation(#20089,#20091) scopes(#20000,0) -#20109=@"script;{#10000},9,22" +#20092=@"script;{#10000},13,37" +#20093=* +lines(#20093,#20092," attr2 ","") +#20094=@"loc,{#10000},13,37,13,43" +locations_default(#20094,#10000,13,37,13,43) +hasLocation(#20093,#20094) +indentation(#10000,13," ",1) +numlines(#20092,1,1,0) +#20095=* +tokeninfo(#20095,6,#20092,0,"attr2") +#20096=@"loc,{#10000},13,38,13,42" +locations_default(#20096,#10000,13,38,13,42) +hasLocation(#20095,#20096) +#20097=* +tokeninfo(#20097,0,#20092,1,"") +#20098=@"loc,{#10000},13,44,13,43" +locations_default(#20098,#10000,13,44,13,43) +hasLocation(#20097,#20098) +toplevels(#20092,4) +hasLocation(#20092,#20094) +#20099=@"module;{#10000},13,37" +scopes(#20099,3) +scopenodes(#20092,#20099) +scopenesting(#20099,#20000) +is_module(#20092) +#20100=* +stmts(#20100,2,#20092,0,"attr2") +hasLocation(#20100,#20096) +stmt_containers(#20100,#20092) +#20101=* +exprs(#20101,79,#20100,0,"attr2") +hasLocation(#20101,#20096) +enclosing_stmt(#20101,#20100) +expr_containers(#20101,#20092) +literals("attr2","attr2",#20101) +#20102=@"var;{attr2};{#20099}" +variables(#20102,"attr2",#20099) +bind(#20101,#20102) +#20103=* +entry_cfg_node(#20103,#20092) +#20104=@"loc,{#10000},13,37,13,36" +locations_default(#20104,#10000,13,37,13,36) +hasLocation(#20103,#20104) +#20105=* +exit_cfg_node(#20105,#20092) +hasLocation(#20105,#20098) +successor(#20100,#20101) +successor(#20101,#20105) +successor(#20103,#20100) +toplevel_parent_xml_node(#20092,#20089) +#20106=* +#20107=* +template_placeholder_tag_info(#20106,#20107,"<%- attr3 %>") +#20108=@"loc,{#10000},13,59,13,70" +locations_default(#20108,#10000,13,59,13,70) +hasLocation(#20106,#20108) +scopes(#20000,0) +#20109=@"script;{#10000},13,62" #20110=* -lines(#20110,#20109," user_data1 ","") -#20111=@"loc,{#10000},9,22,9,33" -locations_default(#20111,#10000,9,22,9,33) +lines(#20110,#20109," attr3 ","") +#20111=@"loc,{#10000},13,62,13,68" +locations_default(#20111,#10000,13,62,13,68) hasLocation(#20110,#20111) -indentation(#10000,9," ",1) +indentation(#10000,13," ",1) numlines(#20109,1,1,0) #20112=* -tokeninfo(#20112,6,#20109,0,"user_data1") -#20113=@"loc,{#10000},9,23,9,32" -locations_default(#20113,#10000,9,23,9,32) +tokeninfo(#20112,6,#20109,0,"attr3") +#20113=@"loc,{#10000},13,63,13,67" +locations_default(#20113,#10000,13,63,13,67) hasLocation(#20112,#20113) #20114=* tokeninfo(#20114,0,#20109,1,"") -#20115=@"loc,{#10000},9,34,9,33" -locations_default(#20115,#10000,9,34,9,33) +#20115=@"loc,{#10000},13,69,13,68" +locations_default(#20115,#10000,13,69,13,68) hasLocation(#20114,#20115) toplevels(#20109,4) hasLocation(#20109,#20111) -#20116=@"module;{#10000},9,22" +#20116=@"module;{#10000},13,62" scopes(#20116,3) scopenodes(#20109,#20116) scopenesting(#20116,#20000) is_module(#20109) #20117=* -stmts(#20117,2,#20109,0,"user_data1") +stmts(#20117,2,#20109,0,"attr3") hasLocation(#20117,#20113) stmt_containers(#20117,#20109) #20118=* -exprs(#20118,79,#20117,0,"user_data1") +exprs(#20118,79,#20117,0,"attr3") hasLocation(#20118,#20113) enclosing_stmt(#20118,#20117) expr_containers(#20118,#20109) -literals("user_data1","user_data1",#20118) -#20119=@"var;{user_data1};{#20116}" -variables(#20119,"user_data1",#20116) +literals("attr3","attr3",#20118) +#20119=@"var;{attr3};{#20116}" +variables(#20119,"attr3",#20116) bind(#20118,#20119) #20120=* entry_cfg_node(#20120,#20109) -#20121=@"loc,{#10000},9,22,9,21" -locations_default(#20121,#10000,9,22,9,21) +#20121=@"loc,{#10000},13,62,13,61" +locations_default(#20121,#10000,13,62,13,61) hasLocation(#20120,#20121) #20122=* exit_cfg_node(#20122,#20109) @@ -407,376 +407,631 @@ hasLocation(#20122,#20115) successor(#20117,#20118) successor(#20118,#20122) successor(#20120,#20117) -toplevel_parent_xml_node(#20109,#20108) +toplevel_parent_xml_node(#20109,#20106) #20123=* -template_placeholder_tag_info(#20123,#20001,"{{ user_data2 | json | safe }}") -locations_default(#20062,#10000,10,19,10,48) -hasLocation(#20123,#20062) +#20124=* +template_placeholder_tag_info(#20123,#20124,"{{ attr4 }}") +#20125=@"loc,{#10000},14,21,14,31" +locations_default(#20125,#10000,14,21,14,31) +hasLocation(#20123,#20125) scopes(#20000,0) -#20124=@"script;{#10000},10,21" -#20125=* -lines(#20125,#20124," user_data2 | json | safe ","") -#20126=@"loc,{#10000},10,21,10,46" -locations_default(#20126,#10000,10,21,10,46) -hasLocation(#20125,#20126) -indentation(#10000,10," ",1) -numlines(#20124,1,1,0) +#20126=@"script;{#10000},14,23" #20127=* -tokeninfo(#20127,6,#20124,0,"user_data2") -#20128=@"loc,{#10000},10,22,10,31" -locations_default(#20128,#10000,10,22,10,31) +lines(#20127,#20126," attr4 ","") +#20128=@"loc,{#10000},14,23,14,29" +locations_default(#20128,#10000,14,23,14,29) hasLocation(#20127,#20128) +indentation(#10000,14," ",1) +numlines(#20126,1,1,0) #20129=* -tokeninfo(#20129,8,#20124,1,"|") -#20130=@"loc,{#10000},10,33,10,33" -locations_default(#20130,#10000,10,33,10,33) +tokeninfo(#20129,6,#20126,0,"attr4") +#20130=@"loc,{#10000},14,24,14,28" +locations_default(#20130,#10000,14,24,14,28) hasLocation(#20129,#20130) #20131=* -tokeninfo(#20131,6,#20124,2,"json") -#20132=@"loc,{#10000},10,35,10,38" -locations_default(#20132,#10000,10,35,10,38) +tokeninfo(#20131,0,#20126,1,"") +#20132=@"loc,{#10000},14,30,14,29" +locations_default(#20132,#10000,14,30,14,29) hasLocation(#20131,#20132) -#20133=* -tokeninfo(#20133,8,#20124,3,"|") -#20134=@"loc,{#10000},10,40,10,40" -locations_default(#20134,#10000,10,40,10,40) -hasLocation(#20133,#20134) +toplevels(#20126,4) +hasLocation(#20126,#20128) +#20133=@"module;{#10000},14,23" +scopes(#20133,3) +scopenodes(#20126,#20133) +scopenesting(#20133,#20000) +is_module(#20126) +#20134=* +stmts(#20134,2,#20126,0,"attr4") +hasLocation(#20134,#20130) +stmt_containers(#20134,#20126) #20135=* -tokeninfo(#20135,6,#20124,4,"safe") -#20136=@"loc,{#10000},10,42,10,45" -locations_default(#20136,#10000,10,42,10,45) -hasLocation(#20135,#20136) +exprs(#20135,79,#20134,0,"attr4") +hasLocation(#20135,#20130) +enclosing_stmt(#20135,#20134) +expr_containers(#20135,#20126) +literals("attr4","attr4",#20135) +#20136=@"var;{attr4};{#20133}" +variables(#20136,"attr4",#20133) +bind(#20135,#20136) #20137=* -tokeninfo(#20137,0,#20124,5,"") -#20138=@"loc,{#10000},10,47,10,46" -locations_default(#20138,#10000,10,47,10,46) +entry_cfg_node(#20137,#20126) +#20138=@"loc,{#10000},14,23,14,22" +locations_default(#20138,#10000,14,23,14,22) hasLocation(#20137,#20138) -toplevels(#20124,4) -hasLocation(#20124,#20126) -#20139=@"module;{#10000},10,21" -scopes(#20139,3) -scopenodes(#20124,#20139) -scopenesting(#20139,#20000) -is_module(#20124) +#20139=* +exit_cfg_node(#20139,#20126) +hasLocation(#20139,#20132) +successor(#20134,#20135) +successor(#20135,#20139) +successor(#20137,#20134) +toplevel_parent_xml_node(#20126,#20123) #20140=* -stmts(#20140,2,#20124,0,"user_da ... | safe") -#20141=@"loc,{#10000},10,22,10,45" -locations_default(#20141,#10000,10,22,10,45) -hasLocation(#20140,#20141) -stmt_containers(#20140,#20124) +xmlChars(#20140," +",#10000,0,0,#10000) +#20141=@"loc,{#10000},1,16,1,16" +locations_default(#20141,#10000,1,16,1,16) +xmllocations(#20140,#20141) #20142=* -exprs(#20142,13,#20140,0,"user_da ... | safe") -hasLocation(#20142,#20141) -enclosing_stmt(#20142,#20140) -expr_containers(#20142,#20124) -#20143=* -exprs(#20143,119,#20142,-1,"safe") -hasLocation(#20143,#20136) -enclosing_stmt(#20143,#20140) -expr_containers(#20143,#20124) +xmlElements(#20142,"html",#10000,1,#10000) +#20143=@"loc,{#10000},2,1,16,7" +locations_default(#20143,#10000,2,1,16,7) +xmllocations(#20142,#20143) #20144=* -exprs(#20144,0,#20143,0,"safe") -hasLocation(#20144,#20136) -enclosing_stmt(#20144,#20140) -expr_containers(#20144,#20124) -literals("safe","safe",#20144) -#20145=* -exprs(#20145,13,#20142,0,"user_data2 | json") -#20146=@"loc,{#10000},10,22,10,38" -locations_default(#20146,#10000,10,22,10,38) -hasLocation(#20145,#20146) -enclosing_stmt(#20145,#20140) -expr_containers(#20145,#20124) -#20147=* -exprs(#20147,119,#20145,-1,"json") -hasLocation(#20147,#20132) -enclosing_stmt(#20147,#20140) -expr_containers(#20147,#20124) +xmlChars(#20144," + ",#20142,0,0,#10000) +#20145=@"loc,{#10000},2,7,3,2" +locations_default(#20145,#10000,2,7,3,2) +xmllocations(#20144,#20145) +#20146=* +xmlChars(#20146," +",#20142,2,0,#10000) +#20147=@"loc,{#10000},15,10,15,10" +locations_default(#20147,#10000,15,10,15,10) +xmllocations(#20146,#20147) #20148=* -exprs(#20148,0,#20147,0,"json") -hasLocation(#20148,#20132) -enclosing_stmt(#20148,#20140) -expr_containers(#20148,#20124) -literals("json","json",#20148) -#20149=* -exprs(#20149,79,#20145,0,"user_data2") -hasLocation(#20149,#20128) -enclosing_stmt(#20149,#20140) -expr_containers(#20149,#20124) -literals("user_data2","user_data2",#20149) -#20150=@"var;{user_data2};{#20139}" -variables(#20150,"user_data2",#20139) -bind(#20149,#20150) -#20151=* -entry_cfg_node(#20151,#20124) -#20152=@"loc,{#10000},10,21,10,20" -locations_default(#20152,#10000,10,21,10,20) -hasLocation(#20151,#20152) -#20153=* -exit_cfg_node(#20153,#20124) -hasLocation(#20153,#20138) -successor(#20140,#20143) -successor(#20149,#20145) -successor(#20147,#20149) -successor(#20145,#20142) -successor(#20143,#20147) -successor(#20142,#20153) -successor(#20151,#20140) -toplevel_parent_xml_node(#20124,#20123) -#20154=* -template_placeholder_tag_info(#20154,#20001,"<%- user_data3 %>") -locations_default(#20069,#10000,11,19,11,35) -hasLocation(#20154,#20069) +xmlElements(#20148,"body",#20142,1,#10000) +#20149=@"loc,{#10000},3,3,15,9" +locations_default(#20149,#10000,3,3,15,9) +xmllocations(#20148,#20149) +#20150=* +xmlChars(#20150," + ",#20148,0,0,#10000) +#20151=@"loc,{#10000},3,9,4,4" +locations_default(#20151,#10000,3,9,4,4) +xmllocations(#20150,#20151) +#20152=* +template_placeholder_tag_info(#20152,#20148,"{{{subtitle_html}}}") +#20153=@"loc,{#10000},5,5,5,23" +locations_default(#20153,#10000,5,5,5,23) +hasLocation(#20152,#20153) scopes(#20000,0) -#20155=@"script;{#10000},11,22" -#20156=* -lines(#20156,#20155," user_data3 ","") -#20157=@"loc,{#10000},11,22,11,33" -locations_default(#20157,#10000,11,22,11,33) -hasLocation(#20156,#20157) -indentation(#10000,11," ",1) -numlines(#20155,1,1,0) +#20154=@"script;{#10000},5,8" +#20155=* +lines(#20155,#20154,"subtitle_html","") +#20156=@"loc,{#10000},5,8,5,20" +locations_default(#20156,#10000,5,8,5,20) +hasLocation(#20155,#20156) +numlines(#20154,1,1,0) +#20157=* +tokeninfo(#20157,6,#20154,0,"subtitle_html") +hasLocation(#20157,#20156) #20158=* -tokeninfo(#20158,6,#20155,0,"user_data3") -#20159=@"loc,{#10000},11,23,11,32" -locations_default(#20159,#10000,11,23,11,32) +tokeninfo(#20158,0,#20154,1,"") +#20159=@"loc,{#10000},5,21,5,20" +locations_default(#20159,#10000,5,21,5,20) hasLocation(#20158,#20159) -#20160=* -tokeninfo(#20160,0,#20155,1,"") -#20161=@"loc,{#10000},11,34,11,33" -locations_default(#20161,#10000,11,34,11,33) -hasLocation(#20160,#20161) -toplevels(#20155,4) -hasLocation(#20155,#20157) -#20162=@"module;{#10000},11,22" -scopes(#20162,3) -scopenodes(#20155,#20162) -scopenesting(#20162,#20000) -is_module(#20155) -#20163=* -stmts(#20163,2,#20155,0,"user_data3") -hasLocation(#20163,#20159) -stmt_containers(#20163,#20155) +toplevels(#20154,4) +hasLocation(#20154,#20156) +#20160=@"module;{#10000},5,8" +scopes(#20160,3) +scopenodes(#20154,#20160) +scopenesting(#20160,#20000) +is_module(#20154) +#20161=* +stmts(#20161,2,#20154,0,"subtitle_html") +hasLocation(#20161,#20156) +stmt_containers(#20161,#20154) +#20162=* +exprs(#20162,79,#20161,0,"subtitle_html") +hasLocation(#20162,#20156) +enclosing_stmt(#20162,#20161) +expr_containers(#20162,#20154) +literals("subtitle_html","subtitle_html",#20162) +#20163=@"var;{subtitle_html};{#20160}" +variables(#20163,"subtitle_html",#20160) +bind(#20162,#20163) #20164=* -exprs(#20164,79,#20163,0,"user_data3") -hasLocation(#20164,#20159) -enclosing_stmt(#20164,#20163) -expr_containers(#20164,#20155) -literals("user_data3","user_data3",#20164) -#20165=@"var;{user_data3};{#20162}" -variables(#20165,"user_data3",#20162) -bind(#20164,#20165) +entry_cfg_node(#20164,#20154) +#20165=@"loc,{#10000},5,8,5,7" +locations_default(#20165,#10000,5,8,5,7) +hasLocation(#20164,#20165) #20166=* -entry_cfg_node(#20166,#20155) -#20167=@"loc,{#10000},11,22,11,21" -locations_default(#20167,#10000,11,22,11,21) -hasLocation(#20166,#20167) -#20168=* -exit_cfg_node(#20168,#20155) -hasLocation(#20168,#20161) -successor(#20163,#20164) -successor(#20164,#20168) -successor(#20166,#20163) -toplevel_parent_xml_node(#20155,#20154) +exit_cfg_node(#20166,#20154) +hasLocation(#20166,#20159) +successor(#20161,#20162) +successor(#20162,#20166) +successor(#20164,#20161) +toplevel_parent_xml_node(#20154,#20152) +#20167=* +xmlChars(#20167," + {{{subtitle_html}}} + ",#20148,2,0,#10000) +#20168=@"loc,{#10000},4,23,6,4" +locations_default(#20168,#10000,4,23,6,4) +xmllocations(#20167,#20168) #20169=* xmlChars(#20169," + ",#20148,4,0,#10000) +#20170=@"loc,{#10000},6,28,7,4" +locations_default(#20170,#10000,6,28,7,4) +xmllocations(#20169,#20170) +#20171=* +xmlChars(#20171," + ",#20148,6,0,#10000) +#20172=@"loc,{#10000},7,25,8,4" +locations_default(#20172,#10000,7,25,8,4) +xmllocations(#20171,#20172) +#20173=* +xmlChars(#20173," + ",#20148,8,0,#10000) +#20174=@"loc,{#10000},12,14,13,4" +locations_default(#20174,#10000,12,14,13,4) +xmllocations(#20173,#20174) +#20175=* +xmlChars(#20175," + ",#20148,10,0,#10000) +#20176=@"loc,{#10000},14,39,15,2" +locations_default(#20176,#10000,14,39,15,2) +xmllocations(#20175,#20176) +#20177=* +xmlElements(#20177,"a",#20148,9,#10000) +#20178=@"loc,{#10000},13,5,14,38" +locations_default(#20178,#10000,13,5,14,38) +xmllocations(#20177,#20178) +xmlAttrs(#20073,#20177,"href","{{ attr1 }}",0,#10000) +#20179=@"loc,{#10000},13,8,13,25" +locations_default(#20179,#10000,13,8,13,25) +xmllocations(#20073,#20179) +xmlAttrs(#20090,#20177,"title","{{{ attr2 }}}",1,#10000) +#20180=@"loc,{#10000},13,27,13,47" +locations_default(#20180,#10000,13,27,13,47) +xmllocations(#20090,#20180) +xmlAttrs(#20107,#20177,"data-foo","<%- attr3 %>",2,#10000) +#20181=@"loc,{#10000},13,49,13,71" +locations_default(#20181,#10000,13,49,13,71) +xmllocations(#20107,#20181) +xmlAttrs(#20124,#20177,"data-bar"," {{ attr4 }} ",3,#10000) +#20182=@"loc,{#10000},14,8,14,33" +locations_default(#20182,#10000,14,8,14,33) +xmllocations(#20124,#20182) +xmlElements(#20001,"script",#20148,7,#10000) +#20183=@"loc,{#10000},8,5,12,13" +locations_default(#20183,#10000,8,5,12,13) +xmllocations(#20001,#20183) +#20184=* +template_placeholder_tag_info(#20184,#20001,"{{{ user_data1 }}}") +locations_default(#20055,#10000,9,19,9,36) +hasLocation(#20184,#20055) +scopes(#20000,0) +#20185=@"script;{#10000},9,22" +#20186=* +lines(#20186,#20185," user_data1 ","") +#20187=@"loc,{#10000},9,22,9,33" +locations_default(#20187,#10000,9,22,9,33) +hasLocation(#20186,#20187) +indentation(#10000,9," ",1) +numlines(#20185,1,1,0) +#20188=* +tokeninfo(#20188,6,#20185,0,"user_data1") +#20189=@"loc,{#10000},9,23,9,32" +locations_default(#20189,#10000,9,23,9,32) +hasLocation(#20188,#20189) +#20190=* +tokeninfo(#20190,0,#20185,1,"") +#20191=@"loc,{#10000},9,34,9,33" +locations_default(#20191,#10000,9,34,9,33) +hasLocation(#20190,#20191) +toplevels(#20185,4) +hasLocation(#20185,#20187) +#20192=@"module;{#10000},9,22" +scopes(#20192,3) +scopenodes(#20185,#20192) +scopenesting(#20192,#20000) +is_module(#20185) +#20193=* +stmts(#20193,2,#20185,0,"user_data1") +hasLocation(#20193,#20189) +stmt_containers(#20193,#20185) +#20194=* +exprs(#20194,79,#20193,0,"user_data1") +hasLocation(#20194,#20189) +enclosing_stmt(#20194,#20193) +expr_containers(#20194,#20185) +literals("user_data1","user_data1",#20194) +#20195=@"var;{user_data1};{#20192}" +variables(#20195,"user_data1",#20192) +bind(#20194,#20195) +#20196=* +entry_cfg_node(#20196,#20185) +#20197=@"loc,{#10000},9,22,9,21" +locations_default(#20197,#10000,9,22,9,21) +hasLocation(#20196,#20197) +#20198=* +exit_cfg_node(#20198,#20185) +hasLocation(#20198,#20191) +successor(#20193,#20194) +successor(#20194,#20198) +successor(#20196,#20193) +toplevel_parent_xml_node(#20185,#20184) +#20199=* +template_placeholder_tag_info(#20199,#20001,"{{ user_data2 | json | safe }}") +locations_default(#20062,#10000,10,19,10,48) +hasLocation(#20199,#20062) +scopes(#20000,0) +#20200=@"script;{#10000},10,21" +#20201=* +lines(#20201,#20200," user_data2 | json | safe ","") +#20202=@"loc,{#10000},10,21,10,46" +locations_default(#20202,#10000,10,21,10,46) +hasLocation(#20201,#20202) +indentation(#10000,10," ",1) +numlines(#20200,1,1,0) +#20203=* +tokeninfo(#20203,6,#20200,0,"user_data2") +#20204=@"loc,{#10000},10,22,10,31" +locations_default(#20204,#10000,10,22,10,31) +hasLocation(#20203,#20204) +#20205=* +tokeninfo(#20205,8,#20200,1,"|") +#20206=@"loc,{#10000},10,33,10,33" +locations_default(#20206,#10000,10,33,10,33) +hasLocation(#20205,#20206) +#20207=* +tokeninfo(#20207,6,#20200,2,"json") +#20208=@"loc,{#10000},10,35,10,38" +locations_default(#20208,#10000,10,35,10,38) +hasLocation(#20207,#20208) +#20209=* +tokeninfo(#20209,8,#20200,3,"|") +#20210=@"loc,{#10000},10,40,10,40" +locations_default(#20210,#10000,10,40,10,40) +hasLocation(#20209,#20210) +#20211=* +tokeninfo(#20211,6,#20200,4,"safe") +#20212=@"loc,{#10000},10,42,10,45" +locations_default(#20212,#10000,10,42,10,45) +hasLocation(#20211,#20212) +#20213=* +tokeninfo(#20213,0,#20200,5,"") +#20214=@"loc,{#10000},10,47,10,46" +locations_default(#20214,#10000,10,47,10,46) +hasLocation(#20213,#20214) +toplevels(#20200,4) +hasLocation(#20200,#20202) +#20215=@"module;{#10000},10,21" +scopes(#20215,3) +scopenodes(#20200,#20215) +scopenesting(#20215,#20000) +is_module(#20200) +#20216=* +stmts(#20216,2,#20200,0,"user_da ... | safe") +#20217=@"loc,{#10000},10,22,10,45" +locations_default(#20217,#10000,10,22,10,45) +hasLocation(#20216,#20217) +stmt_containers(#20216,#20200) +#20218=* +exprs(#20218,13,#20216,0,"user_da ... | safe") +hasLocation(#20218,#20217) +enclosing_stmt(#20218,#20216) +expr_containers(#20218,#20200) +#20219=* +exprs(#20219,119,#20218,-1,"safe") +hasLocation(#20219,#20212) +enclosing_stmt(#20219,#20216) +expr_containers(#20219,#20200) +#20220=* +exprs(#20220,0,#20219,0,"safe") +hasLocation(#20220,#20212) +enclosing_stmt(#20220,#20216) +expr_containers(#20220,#20200) +literals("safe","safe",#20220) +#20221=* +exprs(#20221,13,#20218,0,"user_data2 | json") +#20222=@"loc,{#10000},10,22,10,38" +locations_default(#20222,#10000,10,22,10,38) +hasLocation(#20221,#20222) +enclosing_stmt(#20221,#20216) +expr_containers(#20221,#20200) +#20223=* +exprs(#20223,119,#20221,-1,"json") +hasLocation(#20223,#20208) +enclosing_stmt(#20223,#20216) +expr_containers(#20223,#20200) +#20224=* +exprs(#20224,0,#20223,0,"json") +hasLocation(#20224,#20208) +enclosing_stmt(#20224,#20216) +expr_containers(#20224,#20200) +literals("json","json",#20224) +#20225=* +exprs(#20225,79,#20221,0,"user_data2") +hasLocation(#20225,#20204) +enclosing_stmt(#20225,#20216) +expr_containers(#20225,#20200) +literals("user_data2","user_data2",#20225) +#20226=@"var;{user_data2};{#20215}" +variables(#20226,"user_data2",#20215) +bind(#20225,#20226) +#20227=* +entry_cfg_node(#20227,#20200) +#20228=@"loc,{#10000},10,21,10,20" +locations_default(#20228,#10000,10,21,10,20) +hasLocation(#20227,#20228) +#20229=* +exit_cfg_node(#20229,#20200) +hasLocation(#20229,#20214) +successor(#20216,#20219) +successor(#20225,#20221) +successor(#20223,#20225) +successor(#20221,#20218) +successor(#20219,#20223) +successor(#20218,#20229) +successor(#20227,#20216) +toplevel_parent_xml_node(#20200,#20199) +#20230=* +template_placeholder_tag_info(#20230,#20001,"<%- user_data3 %>") +locations_default(#20069,#10000,11,19,11,35) +hasLocation(#20230,#20069) +scopes(#20000,0) +#20231=@"script;{#10000},11,22" +#20232=* +lines(#20232,#20231," user_data3 ","") +#20233=@"loc,{#10000},11,22,11,33" +locations_default(#20233,#10000,11,22,11,33) +hasLocation(#20232,#20233) +indentation(#10000,11," ",1) +numlines(#20231,1,1,0) +#20234=* +tokeninfo(#20234,6,#20231,0,"user_data3") +#20235=@"loc,{#10000},11,23,11,32" +locations_default(#20235,#10000,11,23,11,32) +hasLocation(#20234,#20235) +#20236=* +tokeninfo(#20236,0,#20231,1,"") +#20237=@"loc,{#10000},11,34,11,33" +locations_default(#20237,#10000,11,34,11,33) +hasLocation(#20236,#20237) +toplevels(#20231,4) +hasLocation(#20231,#20233) +#20238=@"module;{#10000},11,22" +scopes(#20238,3) +scopenodes(#20231,#20238) +scopenesting(#20238,#20000) +is_module(#20231) +#20239=* +stmts(#20239,2,#20231,0,"user_data3") +hasLocation(#20239,#20235) +stmt_containers(#20239,#20231) +#20240=* +exprs(#20240,79,#20239,0,"user_data3") +hasLocation(#20240,#20235) +enclosing_stmt(#20240,#20239) +expr_containers(#20240,#20231) +literals("user_data3","user_data3",#20240) +#20241=@"var;{user_data3};{#20238}" +variables(#20241,"user_data3",#20238) +bind(#20240,#20241) +#20242=* +entry_cfg_node(#20242,#20231) +#20243=@"loc,{#10000},11,22,11,21" +locations_default(#20243,#10000,11,22,11,21) +hasLocation(#20242,#20243) +#20244=* +exit_cfg_node(#20244,#20231) +hasLocation(#20244,#20237) +successor(#20239,#20240) +successor(#20240,#20244) +successor(#20242,#20239) +toplevel_parent_xml_node(#20231,#20230) +#20245=* +xmlChars(#20245," var data1 = {{{ user_data1 }}}; var data2 = {{ user_data2 | json | safe }}; var data3 = <%- user_data3 %>; ",#20001,0,0,#10000) locations_default(#20045,#10000,8,13,12,4) -xmllocations(#20169,#20045) -#20170=* -xmlElements(#20170,"p",#20080,5,#10000) -#20171=@"loc,{#10000},7,5,7,24" -locations_default(#20171,#10000,7,5,7,24) -xmllocations(#20170,#20171) -#20172=* -template_placeholder_tag_info(#20172,#20170,"<%= footer %>") -#20173=@"loc,{#10000},7,8,7,20" -locations_default(#20173,#10000,7,8,7,20) -hasLocation(#20172,#20173) +xmllocations(#20245,#20045) +#20246=* +xmlElements(#20246,"p",#20148,5,#10000) +#20247=@"loc,{#10000},7,5,7,24" +locations_default(#20247,#10000,7,5,7,24) +xmllocations(#20246,#20247) +#20248=* +template_placeholder_tag_info(#20248,#20246,"<%= footer %>") +#20249=@"loc,{#10000},7,8,7,20" +locations_default(#20249,#10000,7,8,7,20) +hasLocation(#20248,#20249) scopes(#20000,0) -#20174=@"script;{#10000},7,11" -#20175=* -lines(#20175,#20174," footer ","") -#20176=@"loc,{#10000},7,11,7,18" -locations_default(#20176,#10000,7,11,7,18) -hasLocation(#20175,#20176) +#20250=@"script;{#10000},7,11" +#20251=* +lines(#20251,#20250," footer ","") +#20252=@"loc,{#10000},7,11,7,18" +locations_default(#20252,#10000,7,11,7,18) +hasLocation(#20251,#20252) indentation(#10000,7," ",1) -numlines(#20174,1,1,0) -#20177=* -tokeninfo(#20177,6,#20174,0,"footer") -#20178=@"loc,{#10000},7,12,7,17" -locations_default(#20178,#10000,7,12,7,17) -hasLocation(#20177,#20178) -#20179=* -tokeninfo(#20179,0,#20174,1,"") -#20180=@"loc,{#10000},7,19,7,18" -locations_default(#20180,#10000,7,19,7,18) -hasLocation(#20179,#20180) -toplevels(#20174,4) -hasLocation(#20174,#20176) -#20181=@"module;{#10000},7,11" -scopes(#20181,3) -scopenodes(#20174,#20181) -scopenesting(#20181,#20000) -is_module(#20174) -#20182=* -stmts(#20182,2,#20174,0,"footer") -hasLocation(#20182,#20178) -stmt_containers(#20182,#20174) -#20183=* -exprs(#20183,79,#20182,0,"footer") -hasLocation(#20183,#20178) -enclosing_stmt(#20183,#20182) -expr_containers(#20183,#20174) -literals("footer","footer",#20183) -#20184=@"var;{footer};{#20181}" -variables(#20184,"footer",#20181) -bind(#20183,#20184) -#20185=* -entry_cfg_node(#20185,#20174) -#20186=@"loc,{#10000},7,11,7,10" -locations_default(#20186,#10000,7,11,7,10) -hasLocation(#20185,#20186) -#20187=* -exit_cfg_node(#20187,#20174) -hasLocation(#20187,#20180) -successor(#20182,#20183) -successor(#20183,#20187) -successor(#20185,#20182) -toplevel_parent_xml_node(#20174,#20172) -#20188=* -xmlChars(#20188,"<%= footer %>",#20170,0,0,#10000) -locations_default(#20173,#10000,7,8,7,20) -xmllocations(#20188,#20173) -#20189=* -xmlElements(#20189,"p",#20080,3,#10000) -#20190=@"loc,{#10000},6,5,6,27" -locations_default(#20190,#10000,6,5,6,27) -xmllocations(#20189,#20190) -#20191=* -template_placeholder_tag_info(#20191,#20189,"<%- body_html %>") -#20192=@"loc,{#10000},6,8,6,23" -locations_default(#20192,#10000,6,8,6,23) -hasLocation(#20191,#20192) +numlines(#20250,1,1,0) +#20253=* +tokeninfo(#20253,6,#20250,0,"footer") +#20254=@"loc,{#10000},7,12,7,17" +locations_default(#20254,#10000,7,12,7,17) +hasLocation(#20253,#20254) +#20255=* +tokeninfo(#20255,0,#20250,1,"") +#20256=@"loc,{#10000},7,19,7,18" +locations_default(#20256,#10000,7,19,7,18) +hasLocation(#20255,#20256) +toplevels(#20250,4) +hasLocation(#20250,#20252) +#20257=@"module;{#10000},7,11" +scopes(#20257,3) +scopenodes(#20250,#20257) +scopenesting(#20257,#20000) +is_module(#20250) +#20258=* +stmts(#20258,2,#20250,0,"footer") +hasLocation(#20258,#20254) +stmt_containers(#20258,#20250) +#20259=* +exprs(#20259,79,#20258,0,"footer") +hasLocation(#20259,#20254) +enclosing_stmt(#20259,#20258) +expr_containers(#20259,#20250) +literals("footer","footer",#20259) +#20260=@"var;{footer};{#20257}" +variables(#20260,"footer",#20257) +bind(#20259,#20260) +#20261=* +entry_cfg_node(#20261,#20250) +#20262=@"loc,{#10000},7,11,7,10" +locations_default(#20262,#10000,7,11,7,10) +hasLocation(#20261,#20262) +#20263=* +exit_cfg_node(#20263,#20250) +hasLocation(#20263,#20256) +successor(#20258,#20259) +successor(#20259,#20263) +successor(#20261,#20258) +toplevel_parent_xml_node(#20250,#20248) +#20264=* +xmlChars(#20264,"<%= footer %>",#20246,0,0,#10000) +locations_default(#20249,#10000,7,8,7,20) +xmllocations(#20264,#20249) +#20265=* +xmlElements(#20265,"p",#20148,3,#10000) +#20266=@"loc,{#10000},6,5,6,27" +locations_default(#20266,#10000,6,5,6,27) +xmllocations(#20265,#20266) +#20267=* +template_placeholder_tag_info(#20267,#20265,"<%- body_html %>") +#20268=@"loc,{#10000},6,8,6,23" +locations_default(#20268,#10000,6,8,6,23) +hasLocation(#20267,#20268) scopes(#20000,0) -#20193=@"script;{#10000},6,11" -#20194=* -lines(#20194,#20193," body_html ","") -#20195=@"loc,{#10000},6,11,6,21" -locations_default(#20195,#10000,6,11,6,21) -hasLocation(#20194,#20195) +#20269=@"script;{#10000},6,11" +#20270=* +lines(#20270,#20269," body_html ","") +#20271=@"loc,{#10000},6,11,6,21" +locations_default(#20271,#10000,6,11,6,21) +hasLocation(#20270,#20271) indentation(#10000,6," ",1) -numlines(#20193,1,1,0) -#20196=* -tokeninfo(#20196,6,#20193,0,"body_html") -#20197=@"loc,{#10000},6,12,6,20" -locations_default(#20197,#10000,6,12,6,20) -hasLocation(#20196,#20197) -#20198=* -tokeninfo(#20198,0,#20193,1,"") -#20199=@"loc,{#10000},6,22,6,21" -locations_default(#20199,#10000,6,22,6,21) -hasLocation(#20198,#20199) -toplevels(#20193,4) -hasLocation(#20193,#20195) -#20200=@"module;{#10000},6,11" -scopes(#20200,3) -scopenodes(#20193,#20200) -scopenesting(#20200,#20000) -is_module(#20193) -#20201=* -stmts(#20201,2,#20193,0,"body_html") -hasLocation(#20201,#20197) -stmt_containers(#20201,#20193) -#20202=* -exprs(#20202,79,#20201,0,"body_html") -hasLocation(#20202,#20197) -enclosing_stmt(#20202,#20201) -expr_containers(#20202,#20193) -literals("body_html","body_html",#20202) -#20203=@"var;{body_html};{#20200}" -variables(#20203,"body_html",#20200) -bind(#20202,#20203) -#20204=* -entry_cfg_node(#20204,#20193) -#20205=@"loc,{#10000},6,11,6,10" -locations_default(#20205,#10000,6,11,6,10) -hasLocation(#20204,#20205) -#20206=* -exit_cfg_node(#20206,#20193) -hasLocation(#20206,#20199) -successor(#20201,#20202) -successor(#20202,#20206) -successor(#20204,#20201) -toplevel_parent_xml_node(#20193,#20191) -#20207=* -xmlChars(#20207,"<%- body_html %>",#20189,0,0,#10000) -locations_default(#20192,#10000,6,8,6,23) -xmllocations(#20207,#20192) -#20208=* -xmlElements(#20208,"h1",#20080,1,#10000) -#20209=@"loc,{#10000},4,5,4,22" -locations_default(#20209,#10000,4,5,4,22) -xmllocations(#20208,#20209) -#20210=* -template_placeholder_tag_info(#20210,#20208,"{{title}}") -#20211=@"loc,{#10000},4,9,4,17" -locations_default(#20211,#10000,4,9,4,17) -hasLocation(#20210,#20211) +numlines(#20269,1,1,0) +#20272=* +tokeninfo(#20272,6,#20269,0,"body_html") +#20273=@"loc,{#10000},6,12,6,20" +locations_default(#20273,#10000,6,12,6,20) +hasLocation(#20272,#20273) +#20274=* +tokeninfo(#20274,0,#20269,1,"") +#20275=@"loc,{#10000},6,22,6,21" +locations_default(#20275,#10000,6,22,6,21) +hasLocation(#20274,#20275) +toplevels(#20269,4) +hasLocation(#20269,#20271) +#20276=@"module;{#10000},6,11" +scopes(#20276,3) +scopenodes(#20269,#20276) +scopenesting(#20276,#20000) +is_module(#20269) +#20277=* +stmts(#20277,2,#20269,0,"body_html") +hasLocation(#20277,#20273) +stmt_containers(#20277,#20269) +#20278=* +exprs(#20278,79,#20277,0,"body_html") +hasLocation(#20278,#20273) +enclosing_stmt(#20278,#20277) +expr_containers(#20278,#20269) +literals("body_html","body_html",#20278) +#20279=@"var;{body_html};{#20276}" +variables(#20279,"body_html",#20276) +bind(#20278,#20279) +#20280=* +entry_cfg_node(#20280,#20269) +#20281=@"loc,{#10000},6,11,6,10" +locations_default(#20281,#10000,6,11,6,10) +hasLocation(#20280,#20281) +#20282=* +exit_cfg_node(#20282,#20269) +hasLocation(#20282,#20275) +successor(#20277,#20278) +successor(#20278,#20282) +successor(#20280,#20277) +toplevel_parent_xml_node(#20269,#20267) +#20283=* +xmlChars(#20283,"<%- body_html %>",#20265,0,0,#10000) +locations_default(#20268,#10000,6,8,6,23) +xmllocations(#20283,#20268) +#20284=* +xmlElements(#20284,"h1",#20148,1,#10000) +#20285=@"loc,{#10000},4,5,4,22" +locations_default(#20285,#10000,4,5,4,22) +xmllocations(#20284,#20285) +#20286=* +template_placeholder_tag_info(#20286,#20284,"{{title}}") +#20287=@"loc,{#10000},4,9,4,17" +locations_default(#20287,#10000,4,9,4,17) +hasLocation(#20286,#20287) scopes(#20000,0) -#20212=@"script;{#10000},4,11" -#20213=* -lines(#20213,#20212,"title","") -#20214=@"loc,{#10000},4,11,4,15" -locations_default(#20214,#10000,4,11,4,15) -hasLocation(#20213,#20214) -numlines(#20212,1,1,0) -#20215=* -tokeninfo(#20215,6,#20212,0,"title") -hasLocation(#20215,#20214) -#20216=* -tokeninfo(#20216,0,#20212,1,"") -#20217=@"loc,{#10000},4,16,4,15" -locations_default(#20217,#10000,4,16,4,15) -hasLocation(#20216,#20217) -toplevels(#20212,4) -hasLocation(#20212,#20214) -#20218=@"module;{#10000},4,11" -scopes(#20218,3) -scopenodes(#20212,#20218) -scopenesting(#20218,#20000) -is_module(#20212) -#20219=* -stmts(#20219,2,#20212,0,"title") -hasLocation(#20219,#20214) -stmt_containers(#20219,#20212) -#20220=* -exprs(#20220,79,#20219,0,"title") -hasLocation(#20220,#20214) -enclosing_stmt(#20220,#20219) -expr_containers(#20220,#20212) -literals("title","title",#20220) -#20221=@"var;{title};{#20218}" -variables(#20221,"title",#20218) -bind(#20220,#20221) -#20222=* -entry_cfg_node(#20222,#20212) -#20223=@"loc,{#10000},4,11,4,10" -locations_default(#20223,#10000,4,11,4,10) -hasLocation(#20222,#20223) -#20224=* -exit_cfg_node(#20224,#20212) -hasLocation(#20224,#20217) -successor(#20219,#20220) -successor(#20220,#20224) -successor(#20222,#20219) -toplevel_parent_xml_node(#20212,#20210) -#20225=* -xmlChars(#20225,"{{title}}",#20208,0,0,#10000) -locations_default(#20211,#10000,4,9,4,17) -xmllocations(#20225,#20211) -numlines(#10000,14,10,0) +#20288=@"script;{#10000},4,11" +#20289=* +lines(#20289,#20288,"title","") +#20290=@"loc,{#10000},4,11,4,15" +locations_default(#20290,#10000,4,11,4,15) +hasLocation(#20289,#20290) +numlines(#20288,1,1,0) +#20291=* +tokeninfo(#20291,6,#20288,0,"title") +hasLocation(#20291,#20290) +#20292=* +tokeninfo(#20292,0,#20288,1,"") +#20293=@"loc,{#10000},4,16,4,15" +locations_default(#20293,#10000,4,16,4,15) +hasLocation(#20292,#20293) +toplevels(#20288,4) +hasLocation(#20288,#20290) +#20294=@"module;{#10000},4,11" +scopes(#20294,3) +scopenodes(#20288,#20294) +scopenesting(#20294,#20000) +is_module(#20288) +#20295=* +stmts(#20295,2,#20288,0,"title") +hasLocation(#20295,#20290) +stmt_containers(#20295,#20288) +#20296=* +exprs(#20296,79,#20295,0,"title") +hasLocation(#20296,#20290) +enclosing_stmt(#20296,#20295) +expr_containers(#20296,#20288) +literals("title","title",#20296) +#20297=@"var;{title};{#20294}" +variables(#20297,"title",#20294) +bind(#20296,#20297) +#20298=* +entry_cfg_node(#20298,#20288) +#20299=@"loc,{#10000},4,11,4,10" +locations_default(#20299,#10000,4,11,4,10) +hasLocation(#20298,#20299) +#20300=* +exit_cfg_node(#20300,#20288) +hasLocation(#20300,#20293) +successor(#20295,#20296) +successor(#20296,#20300) +successor(#20298,#20295) +toplevel_parent_xml_node(#20288,#20286) +#20301=* +xmlChars(#20301,"{{title}}",#20284,0,0,#10000) +locations_default(#20287,#10000,4,9,4,17) +xmllocations(#20301,#20287) +numlines(#10000,16,14,0) filetype(#10000,"html") From a1819a54f222efec49263eb5a13d9f17ade608f0 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 19 Aug 2021 14:22:05 +0200 Subject: [PATCH 305/429] JS: Remove unused isInPlainCodeContext --- .../ql/src/semmle/javascript/frameworks/Templating.qll | 6 ------ 1 file changed, 6 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 50a34a69ea5..a370fc89c25 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -116,12 +116,6 @@ module Templating { not getRawText().regexpMatch("(?s)\\{\\{.*\\}\\}") } - /** - * Holds if this occurs in generated code as an expression or statement, - * that is, without being enclosed in a string literal or similar. - */ - predicate isInPlainCodeContext() { this = any(GeneratedCodeExpr e).getPlaceholderTag() } - /** * Gets the innermost JavaScript expression containing this template tag, if any. */ From bac212c610b904a7d43305bc73276d03d3d9177b Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 19 Aug 2021 14:41:12 +0200 Subject: [PATCH 306/429] JS: Fix typo: instantiaton -> instantiation --- .../semmle/javascript/frameworks/Express.qll | 2 +- .../semmle/javascript/frameworks/Fastify.qll | 2 +- .../src/semmle/javascript/frameworks/Hapi.qll | 2 +- .../src/semmle/javascript/frameworks/Koa.qll | 2 +- .../javascript/frameworks/Templating.qll | 18 +++++++++--------- .../frameworks/Templating/test.ql | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll index 9b88b52d3ef..a68156f6c6d 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll @@ -976,7 +976,7 @@ module Express { /** * A call to the Express `res.render()` method, seen as a template instantiation. */ - private class RenderCallAsTemplateInstantiation extends Templating::TemplateInstantiaton::Range, + private class RenderCallAsTemplateInstantiation extends Templating::TemplateInstantiation::Range, DataFlow::CallNode { RenderCallAsTemplateInstantiation() { this = any(ResponseSource res).ref().getAMethodCall("render") diff --git a/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll index 71e1fc69039..08c9b765f13 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll @@ -294,7 +294,7 @@ module Fastify { * * Assumes the presense of a plugin that provides the `view` method, such as the `point-of-view` plugin. */ - private class ViewCall extends Templating::TemplateInstantiaton::Range, DataFlow::CallNode { + private class ViewCall extends Templating::TemplateInstantiation::Range, DataFlow::CallNode { ViewCall() { this = any(ReplySource rep).ref().getAMethodCall("view") } override DataFlow::SourceNode getOutput() { result = getCallback(2).getParameter(1) } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll index f1cf2c80da6..0172002dd37 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll @@ -252,7 +252,7 @@ module Hapi { /** * A call to `h.view('file', { ... })` seen as a template instantiation. */ - private class ViewCall extends Templating::TemplateInstantiaton::Range, DataFlow::CallNode { + private class ViewCall extends Templating::TemplateInstantiation::Range, DataFlow::CallNode { ViewCall() { this = any(RouteHandler rh).getRequestToolkit().getAMethodCall("view") } override DataFlow::SourceNode getOutput() { none() } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll index 83e7862a878..be189df854e 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Koa.qll @@ -431,7 +431,7 @@ module Koa { /** * A call to `ctx.render('file', { ... })`, seen as a template instantiation. */ - private class RenderCall extends Templating::TemplateInstantiaton::Range, DataFlow::CallNode { + private class RenderCall extends Templating::TemplateInstantiation::Range, DataFlow::CallNode { ContextSource ctx; RenderCall() { this = ctx.ref().getAMethodCall("render") } diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index a370fc89c25..400901b33ee 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -176,10 +176,10 @@ module Templating { /** * A place where a template is instantiated or rendered. */ - class TemplateInstantiaton extends DataFlow::Node { - TemplateInstantiaton::Range range; + class TemplateInstantiation extends DataFlow::Node { + TemplateInstantiation::Range range; - TemplateInstantiaton() { this = range } + TemplateInstantiation() { this = range } /** Gets a data flow node that refers to the instantiated template string, if any. */ DataFlow::SourceNode getOutput() { result = range.getOutput() } @@ -204,7 +204,7 @@ module Templating { } /** Companion module to the `TemplateInstantiation` class. */ - module TemplateInstantiaton { + module TemplateInstantiation { abstract class Range extends DataFlow::Node { /** Gets a data flow node that refers to the instantiated template, if any. */ abstract DataFlow::SourceNode getOutput(); @@ -226,7 +226,7 @@ module Templating { /** Gets an API node that may flow to `succ` through a template instantiation. */ private API::Node getTemplateInput(DataFlow::SourceNode succ) { - exists(TemplateInstantiaton inst, API::Node base, string name | + exists(TemplateInstantiation inst, API::Node base, string name | base.getARhs() = inst.getTemplateParamsNode() and result = base.getMember(name) and succ = @@ -321,7 +321,7 @@ module Templating { /** Get file argument of a template instantiation, seen as a template file reference. */ private class DefaultTemplateFileReference extends TemplateFileReference { - DefaultTemplateFileReference() { this = any(TemplateInstantiaton inst).getTemplateFileNode() } + DefaultTemplateFileReference() { this = any(TemplateInstantiation inst).getTemplateFileNode() } } /** @@ -581,7 +581,7 @@ module Templating { } private TemplateSyntax getTemplateSyntaxFromInstantiation(TemplateFile file) { - result = any(TemplateInstantiaton inst | inst.getTemplateFile() = file).getTemplateSyntax() + result = any(TemplateInstantiation inst | inst.getTemplateFile() = file).getTemplateSyntax() } /** @@ -612,7 +612,7 @@ module Templating { /** * An EJS-style `include` call within a template tag, such as `<%- include(file, { params }) %>`. */ - private class EjsIncludeCallInTemplate extends TemplateInstantiaton::Range, DataFlow::CallNode { + private class EjsIncludeCallInTemplate extends TemplateInstantiation::Range, DataFlow::CallNode { EjsIncludeCallInTemplate() { exists(TemplatePlaceholderTag tag | tag.getRawText().regexpMatch("(?s)<%-.*") and @@ -685,7 +685,7 @@ module Templating { /** * A call to a member of the `consolidate` library, seen as a template instantiation. */ - private class ConsolidateCall extends TemplateInstantiaton::Range, API::CallNode { + private class ConsolidateCall extends TemplateInstantiation::Range, API::CallNode { string engine; ConsolidateCall() { this = API::moduleImport("consolidate").getMember(engine).getACall() } diff --git a/javascript/ql/test/library-tests/frameworks/Templating/test.ql b/javascript/ql/test/library-tests/frameworks/Templating/test.ql index 15391e91f39..c439fa34d6a 100644 --- a/javascript/ql/test/library-tests/frameworks/Templating/test.ql +++ b/javascript/ql/test/library-tests/frameworks/Templating/test.ql @@ -3,7 +3,7 @@ import semmle.javascript.security.dataflow.Xss import semmle.javascript.security.dataflow.CodeInjectionCustomizations query Templating::TemplateSyntax getTemplateInstantiationSyntax( - Templating::TemplateInstantiaton inst + Templating::TemplateInstantiation inst ) { result = inst.getTemplateSyntax() } @@ -12,7 +12,7 @@ query Templating::TemplateSyntax getLikelyTemplateSyntax(Templating::TemplateFil result = Templating::getLikelyTemplateSyntax(file) } -query Templating::TemplateFile getTargetFile(Templating::TemplateInstantiaton inst) { +query Templating::TemplateFile getTargetFile(Templating::TemplateInstantiation inst) { result = inst.getTemplateFile() } From 2553338bce8e9942552ed71b9786494d4ad90c2a Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Thu, 19 Aug 2021 14:54:05 +0200 Subject: [PATCH 307/429] JS: Autoformat {AST,HTML}Extractor.java --- .../com/semmle/js/extractor/ASTExtractor.java | 109 ++++++++++-------- .../semmle/js/extractor/HTMLExtractor.java | 6 +- 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 7898c4b8e34..6796f262fef 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -174,7 +174,8 @@ public class ASTExtractor { private final RegExpExtractor regexpExtractor; private final ExtractorConfig config; - public ASTExtractor(ExtractorConfig config, LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { + public ASTExtractor( + ExtractorConfig config, LexicalExtractor lexicalExtractor, ScopeManager scopeManager) { this.config = config; this.trapwriter = lexicalExtractor.getTrapwriter(); this.locationManager = lexicalExtractor.getLocationManager(); @@ -182,22 +183,22 @@ public class ASTExtractor { this.scopeManager = scopeManager; this.lexicalExtractor = lexicalExtractor; this.regexpExtractor = new RegExpExtractor(trapwriter, locationManager); - this.toplevelLabel = makeTopLevelLabel(trapwriter, 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. - *

    - * May be used to refer to the top-level before it has been extracted. + * + *

    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 static Label makeTopLevelLabel( + TrapWriter trapWriter, Label fileLabel, int startLine, int startColumn) { + return trapWriter.globalID("script;{" + fileLabel + "}," + startLine + ',' + startColumn); } public TrapWriter getTrapwriter() { @@ -254,8 +255,8 @@ public class ASTExtractor { TYPE_LABEL, /** - * 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. + * 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. * *

    This is generally treated as a type, except a variable binding will be emitted for it. */ @@ -273,16 +274,16 @@ public class ASTExtractor { /** * An identifier that occurs in a type-only import. * - * 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). + *

    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). */ TYPE_ONLY_IMPORT, /** * An identifier that occurs in a type-only export. * - * 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). + *

    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). */ TYPE_ONLY_EXPORT, @@ -302,8 +303,8 @@ public class ASTExtractor { EXPORT, /** - * An identifier that occurs as a qualified name in a default export expression, such as - * A in export default A.B. + * An identifier that occurs as a qualified name in a default export expression, such as 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). @@ -314,8 +315,8 @@ public class ASTExtractor { * 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}. * - *

    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. + *

    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 == TYPE_BIND @@ -577,7 +578,9 @@ public class ASTExtractor { Matcher m = TemplateEngines.TEMPLATE_TAGS.matcher(nd.getRaw()); int offset = nd.getLoc().getStart().getOffset(); while (m.find()) { - Label locationLbl = TemplateEngines.makeLocation(lexicalExtractor.getTextualExtractor(), offset + m.start(), offset + m.end()); + Label locationLbl = + TemplateEngines.makeLocation( + lexicalExtractor.getTextualExtractor(), offset + m.start(), offset + m.end()); trapwriter.addTuple("expr_contains_template_tag_location", key, locationLbl); } } @@ -716,7 +719,8 @@ 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); } @@ -1178,9 +1182,7 @@ public class ASTExtractor { return propkey; } - /** - * Extracts the string value of expr as an HTML snippet. - */ + /** Extracts the string value of expr as an HTML snippet. */ private void extractStringValueAsHtml(Expression expr, Label exprLabel) { TextualExtractor textualExtractor = lexicalExtractor.getTextualExtractor(); if (textualExtractor.isSnippet()) { @@ -1193,16 +1195,21 @@ public class ASTExtractor { 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"); - SourceMap sourceMap = textualExtractor.getSourceMap().offsetBy(loc.getStart().getOffset(), sourceAndOffset.snd()); - TextualExtractor innerTextualExtractor = new TextualExtractor( - trapwriter, - locationManager, - source, - false, - getMetrics(), - vfile.toFile(), - sourceMap); + Path vfile = + originalFile.resolveSibling( + originalFile.getFileName().toString() + + "." + + loc.getStart().getLine() + + "." + + loc.getStart().getColumn() + + ".html"); + SourceMap sourceMap = + textualExtractor + .getSourceMap() + .offsetBy(loc.getStart().getOffset(), sourceAndOffset.snd()); + TextualExtractor innerTextualExtractor = + new TextualExtractor( + trapwriter, locationManager, source, false, getMetrics(), vfile.toFile(), sourceMap); HTMLExtractor html = HTMLExtractor.forEmbeddedHtml(config); List

      -
    • © 2021 GitHub, Inc.
    • +
    • © + GitHub, Inc.
    • Terms
    • diff --git a/docs/codeql/index.html b/docs/codeql/index.html index 1173d5a68c4..d69c275afe4 100644 --- a/docs/codeql/index.html +++ b/docs/codeql/index.html @@ -349,11 +349,12 @@
      -
    • © 2021 GitHub, Inc.
    • +
    • © + GitHub, Inc.
    • Terms
    • -
    • Privacy
    From 8939a9b2c1c62b59693a4227707183664ad678dd Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Mon, 23 Aug 2021 14:41:41 +0200 Subject: [PATCH 320/429] C++: Add tests for implicit downcast involving references --- .../ImplicitDowncastFromBitfield/test.cpp | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp index 45922c13cb3..413a3ed800c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp @@ -2,22 +2,42 @@ typedef struct { int x : 24; } my_struct; -int getX1(my_struct m) { +unsigned int getX1(my_struct m) { return m.x; } short getX2(my_struct m) { - return m.x; + return m.x; // BAD } short getX3(my_struct m) { - return (short) m.x; + return (short) m.x; // GOOD } bool getX4(my_struct m) { - return m.x; + return m.x; // GOOD } short getX5(my_struct m) { - return (char) m.x; + return (char) m.x; // GOOD +} + +const char& getx6(my_struct& m) { + const char& result = m.x; // BAD [NOT DETECTED] + return result; +} + +const short& getx7(my_struct& m) { + const short& result = (short) m.x; // GOOD + return result; +} + +const int& getx8(my_struct& m) { + const int& result = m.x; // GOOD + return result; +} + +const bool& getx9(my_struct& m) { + const bool& result = m.x; // GOOD + return result; } From 9324d8f34840c7052f109875010eab61b91179ff Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Mon, 23 Aug 2021 14:44:49 +0200 Subject: [PATCH 321/429] C++: Fix case where implicit downcasts were not detected when using reference --- .../Conversion/ImplicitDowncastFromBitfield.ql | 14 ++++++++++---- .../ImplicitDowncastFromBitfield.expected | 1 + .../ImplicitDowncastFromBitfield/test.cpp | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql index 8ad98ed8d88..74efe8f5cc8 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql @@ -13,10 +13,16 @@ import cpp -from BitField fi, VariableAccess va +from BitField fi, VariableAccess va, Type fct where - fi.getNumBits() > va.getFullyConverted().getType().getSize() * 8 and - va.getExplicitlyConverted().getType().getSize() > va.getFullyConverted().getType().getSize() and + ( + if va.getFullyConverted().getType() instanceof ReferenceType + then fct = va.getFullyConverted().getType().(ReferenceType).getBaseType() + else fct = va.getFullyConverted().getType() + ) and + fi.getNumBits() > fct.getSize() * 8 and + va.getExplicitlyConverted().getType().getSize() > fct.getSize() and va.getTarget() = fi and - not va.getActualType() instanceof BoolType + not fct.getUnspecifiedType() instanceof BoolType and + any() select va, "Implicit downcast of bitfield $@", fi, fi.toString() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/ImplicitDowncastFromBitfield.expected b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/ImplicitDowncastFromBitfield.expected index 194f8698cd2..1bb148c47bd 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/ImplicitDowncastFromBitfield.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/ImplicitDowncastFromBitfield.expected @@ -1 +1,2 @@ | test.cpp:10:11:10:11 | x | Implicit downcast of bitfield $@ | test.cpp:2:6:2:6 | x | x | +| test.cpp:26:25:26:25 | x | Implicit downcast of bitfield $@ | test.cpp:2:6:2:6 | x | x | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp index 413a3ed800c..a597ac0179e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp @@ -23,7 +23,7 @@ short getX5(my_struct m) { } const char& getx6(my_struct& m) { - const char& result = m.x; // BAD [NOT DETECTED] + const char& result = m.x; // BAD return result; } From c04ba7b724eb3cd499bce59b9606bc46c1f90ec8 Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Mon, 23 Aug 2021 14:58:43 +0200 Subject: [PATCH 322/429] C++: Revert benign change of return type from 'unsigned int' to 'int' in testcase, and add 'GOOD' annotation to the testcase --- .../Conversion/ImplicitDowncastFromBitfield/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp index a597ac0179e..3bcb6afe4b4 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/ImplicitDowncastFromBitfield/test.cpp @@ -2,8 +2,8 @@ typedef struct { int x : 24; } my_struct; -unsigned int getX1(my_struct m) { - return m.x; +int getX1(my_struct m) { + return m.x; // GOOD } short getX2(my_struct m) { From 1dc18c4f9c1929ce60ff2d206dd54e29677a1996 Mon Sep 17 00:00:00 2001 From: Shati Patel <42641846+shati-patel@users.noreply.github.com> Date: Mon, 23 Aug 2021 14:37:51 +0100 Subject: [PATCH 323/429] Update docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- .../codeql-for-visual-studio-code/analyzing-your-projects.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 21439a2789f..05b01a4c051 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 @@ -134,7 +134,7 @@ Viewing query results .. pull-quote:: Note Depending on the query, you can also choose different views such as CSV, :ref:`SARIF `, or :ref:`DIL format `. For example, to view the DIL format, right-click a result and select **View DIL**. - The available output views are determined by the format of the query and the metadata. For more information, see ":ref:`CodeQL queries `." + The available output views are determined by the format and the metadata of the query. For more information, see ":ref:`CodeQL queries `." #. Use the dropdown menu in the Results view to choose which results to display, and in what form to display them, such as a formatted alert message or a table of raw results. From 1ee2f6f20788b7d16a182afb18278b84c40998b1 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Mon, 23 Aug 2021 16:05:13 +0200 Subject: [PATCH 324/429] Adapt test generator to new package name --- java/ql/src/utils/GenerateFlowTestCase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/GenerateFlowTestCase.py b/java/ql/src/utils/GenerateFlowTestCase.py index 757a94fe92d..15bdfc2eb87 100755 --- a/java/ql/src/utils/GenerateFlowTestCase.py +++ b/java/ql/src/utils/GenerateFlowTestCase.py @@ -127,7 +127,7 @@ queryDir = os.path.join(workDir, "query") os.makedirs(queryDir) qlFile = os.path.join(queryDir, "gen.ql") with open(os.path.join(queryDir, "qlpack.yml"), "w") as f: - f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql-java") + f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql/java-queries") with open(qlFile, "w") as f: f.write( "import java\nimport utils.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") From a9db1c52e545fd17b126670b8157aedfc059f6ec Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Mon, 23 Aug 2021 13:12:47 +0100 Subject: [PATCH 325/429] All languages: Add getPrimaryQlClasses() This is a non-overridable predicate that concatenates all the getAPrimaryQlClass() results into a comma-separated string. --- cpp/change-notes/2021-08-23-getPrimaryQlClasses.md | 2 ++ cpp/ql/lib/semmle/code/cpp/Element.qll | 5 +++++ csharp/change-notes/2021-08-23-getPrimaryQlClasses.md | 2 ++ csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll | 2 +- csharp/ql/lib/semmle/code/csharp/PrintAst.qll | 2 +- csharp/ql/lib/semmle/code/dotnet/Element.qll | 5 +++++ csharp/ql/test/library-tests/generics/ConsistencyChecks.ql | 2 +- java/change-notes/2021-08-23-getPrimaryQlClasses.md | 2 ++ java/ql/lib/semmle/code/Location.qll | 5 +++++ java/ql/lib/semmle/code/java/PrintAst.qll | 2 +- javascript/change-notes/2021-08-23-getPrimaryQlClasses.md | 2 ++ javascript/ql/src/semmle/javascript/Locations.qll | 5 +++++ javascript/ql/src/semmle/javascript/PrintAst.qll | 4 ++-- 13 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 cpp/change-notes/2021-08-23-getPrimaryQlClasses.md create mode 100644 csharp/change-notes/2021-08-23-getPrimaryQlClasses.md create mode 100644 java/change-notes/2021-08-23-getPrimaryQlClasses.md create mode 100644 javascript/change-notes/2021-08-23-getPrimaryQlClasses.md diff --git a/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md b/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md new file mode 100644 index 00000000000..ebc6aebcfd1 --- /dev/null +++ b/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added `ElementBase.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. diff --git a/cpp/ql/lib/semmle/code/cpp/Element.qll b/cpp/ql/lib/semmle/code/cpp/Element.qll index daa15e0f625..1f547adccaa 100644 --- a/cpp/ql/lib/semmle/code/cpp/Element.qll +++ b/cpp/ql/lib/semmle/code/cpp/Element.qll @@ -58,6 +58,11 @@ class ElementBase extends @element { /** DEPRECATED: use `getAPrimaryQlClass` instead. */ deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() } + /** + * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. + */ + final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + /** * Gets the name of a primary CodeQL class to which this element belongs. * diff --git a/csharp/change-notes/2021-08-23-getPrimaryQlClasses.md b/csharp/change-notes/2021-08-23-getPrimaryQlClasses.md new file mode 100644 index 00000000000..6dbd956cafe --- /dev/null +++ b/csharp/change-notes/2021-08-23-getPrimaryQlClasses.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added `Element.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. diff --git a/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll b/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll index 51b74b2463d..02cfd149886 100644 --- a/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll +++ b/csharp/ql/lib/semmle/code/cil/ConsistencyChecks.qll @@ -670,7 +670,7 @@ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck { override string getMessage() { result = "Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " + - getDeclaration().getAPrimaryQlClass() + getDeclaration().getPrimaryQlClasses() } override string toString() { result = getDeclaration().toStringWithTypes() } diff --git a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll index 1cac4a5f238..a701c7bfbf3 100644 --- a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll @@ -61,7 +61,7 @@ private predicate isNotNeeded(Element e) { * Retrieves the canonical QL class(es) for entity `el` */ private string getQlClass(Element el) { - result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] " + result = "[" + el.getPrimaryQlClasses() + "] " // Alternative implementation -- do not delete. It is useful for QL class discovery. // result = "["+ concat(el.getAQlClass(), ",") + "] " } diff --git a/csharp/ql/lib/semmle/code/dotnet/Element.qll b/csharp/ql/lib/semmle/code/dotnet/Element.qll index 0138766cc58..3b1955887f9 100644 --- a/csharp/ql/lib/semmle/code/dotnet/Element.qll +++ b/csharp/ql/lib/semmle/code/dotnet/Element.qll @@ -40,6 +40,11 @@ class Element extends @dotnet_element { /** Gets the full textual representation of this element, including type information. */ string toStringWithTypes() { result = this.toString() } + /** + * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. + */ + final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + /** * Gets the name of a primary CodeQL class to which this element belongs. * diff --git a/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql b/csharp/ql/test/library-tests/generics/ConsistencyChecks.ql index def07f2c435..7052c6f697a 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.getAPrimaryQlClass() + " has consistency check failed: " + m +select e, "Element class " + e.getPrimaryQlClasses() + " has consistency check failed: " + m diff --git a/java/change-notes/2021-08-23-getPrimaryQlClasses.md b/java/change-notes/2021-08-23-getPrimaryQlClasses.md new file mode 100644 index 00000000000..513cf51bcb0 --- /dev/null +++ b/java/change-notes/2021-08-23-getPrimaryQlClasses.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added `Top.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll index e9b808f6bba..9b3b0dbc2e0 100755 --- a/java/ql/lib/semmle/code/Location.qll +++ b/java/ql/lib/semmle/code/Location.qll @@ -100,6 +100,11 @@ class Top extends @top { cached string toString() { hasName(this, result) } + /** + * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. + */ + final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + /** * Gets the name of a primary CodeQL class to which this element belongs. * diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 6a74c15316c..66f1ecc9449 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -89,7 +89,7 @@ private predicate duplicateMetadata(Field f) { * Retrieves the canonical QL class(es) for entity `el` */ private string getQlClass(Top el) { - result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] " + result = "[" + el.getPrimaryQlClasses() + "] " // Alternative implementation -- do not delete. It is useful for QL class discovery. // result = "[" + concat(el.getAQlClass(), ",") + "] " } diff --git a/javascript/change-notes/2021-08-23-getPrimaryQlClasses.md b/javascript/change-notes/2021-08-23-getPrimaryQlClasses.md new file mode 100644 index 00000000000..c733328f1bd --- /dev/null +++ b/javascript/change-notes/2021-08-23-getPrimaryQlClasses.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Added `Locatable.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. diff --git a/javascript/ql/src/semmle/javascript/Locations.qll b/javascript/ql/src/semmle/javascript/Locations.qll index a84bcd18308..bdf83fb395a 100644 --- a/javascript/ql/src/semmle/javascript/Locations.qll +++ b/javascript/ql/src/semmle/javascript/Locations.qll @@ -132,6 +132,11 @@ class Locatable extends @locatable { none() } + /** + * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. + */ + final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") } + /** * Gets the primary QL class for the Locatable. */ diff --git a/javascript/ql/src/semmle/javascript/PrintAst.qll b/javascript/ql/src/semmle/javascript/PrintAst.qll index 029cfd536fc..5fbcd4f4ec6 100644 --- a/javascript/ql/src/semmle/javascript/PrintAst.qll +++ b/javascript/ql/src/semmle/javascript/PrintAst.qll @@ -44,9 +44,9 @@ private predicate isNotNeeded(Locatable el) { * Retrieves the canonical QL class(es) for entity `el` */ private string getQlClass(Locatable el) { - result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] " + result = "[" + el.getPrimaryQlClasses() + "] " // Alternative implementation -- do not delete. It is useful for QL class discovery. - // not el.getAPrimaryQlClass() = "???" and result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] " or el.getAPrimaryQlClass() = "???" and result = "??[" + concat(el.getAQlClass(), ",") + "] " + // not el.getAPrimaryQlClass() = "???" and result = "[" + getPrimaryQlClasses() + "] " or el.getAPrimaryQlClass() = "???" and result = "??[" + concat(el.getAQlClass(), ",") + "] " } /** From 1e06808105f7c5f8dd000c81f7309b58405819cf Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Mon, 23 Aug 2021 16:52:07 +0100 Subject: [PATCH 326/429] Update cpp/change-notes/2021-08-23-getPrimaryQlClasses.md Co-authored-by: Jonas Jensen --- cpp/change-notes/2021-08-23-getPrimaryQlClasses.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md b/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md index ebc6aebcfd1..6dbd956cafe 100644 --- a/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md +++ b/cpp/change-notes/2021-08-23-getPrimaryQlClasses.md @@ -1,2 +1,2 @@ lgtm,codescanning -* Added `ElementBase.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. +* Added `Element.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. From 6d4b7c828cb0b8c5e92115c8cd89bbf5ddc1639b Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Tue, 24 Aug 2021 09:37:39 +0200 Subject: [PATCH 327/429] C++: Remove superfluous 'and any()' --- .../src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql index 74efe8f5cc8..c2e7e4a6b90 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql @@ -23,6 +23,5 @@ where fi.getNumBits() > fct.getSize() * 8 and va.getExplicitlyConverted().getType().getSize() > fct.getSize() and va.getTarget() = fi and - not fct.getUnspecifiedType() instanceof BoolType and - any() + not fct.getUnspecifiedType() instanceof BoolType select va, "Implicit downcast of bitfield $@", fi, fi.toString() From 6b66f5dbb419da31a5b3fec4b492f20128d079ec Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Tue, 24 Aug 2021 10:26:25 +0200 Subject: [PATCH 328/429] C++: Add change note for implicit downcasting involving references --- cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md diff --git a/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md b/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md new file mode 100644 index 00000000000..2903f13d51a --- /dev/null +++ b/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md @@ -0,0 +1,3 @@ +lgtm,codescanning +* Extend query `ImplicitDowncastFromBitfield` to detect implicit + downcast on references From 7f73efe3e1892a045c77803710e3d3ca10f7d15a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Aug 2021 10:46:01 +0100 Subject: [PATCH 329/429] Downgrade precision of java/concatenated-sql-query --- java/change-notes/2021-08-24-downgrade-sql-unescaped.md | 2 ++ java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 java/change-notes/2021-08-24-downgrade-sql-unescaped.md diff --git a/java/change-notes/2021-08-24-downgrade-sql-unescaped.md b/java/change-notes/2021-08-24-downgrade-sql-unescaped.md new file mode 100644 index 00000000000..afba63e3f54 --- /dev/null +++ b/java/change-notes/2021-08-24-downgrade-sql-unescaped.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Query `java/concatenated-sql-query` has been downgraded to medium precision in view of its heuristic nature, which is inherently prone to false positives. This means its alerts will not be visible by default on lgtm.com. Code Scanning will also no longer run the query by default. diff --git a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql index 6ec2be3e1c8..e9e6cba3770 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql +++ b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.ql @@ -5,7 +5,7 @@ * @kind problem * @problem.severity error * @security-severity 8.8 - * @precision high + * @precision medium * @id java/concatenated-sql-query * @tags security * external/cwe/cwe-089 From 99d7e8b953aeee73cc1fe9af56e052f76389239f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 24 Aug 2021 12:35:20 +0200 Subject: [PATCH 330/429] add change note --- javascript/change-notes/2021-08-24-tainted-path-cwd.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 javascript/change-notes/2021-08-24-tainted-path-cwd.md diff --git a/javascript/change-notes/2021-08-24-tainted-path-cwd.md b/javascript/change-notes/2021-08-24-tainted-path-cwd.md new file mode 100644 index 00000000000..5d4a8f0c68f --- /dev/null +++ b/javascript/change-notes/2021-08-24-tainted-path-cwd.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* The `js/tainted-path` query now recognizes the `cwd` option to shell invocations as a sink. From 8f8a46848d17e0fdebe5350d7f89b4ca3d12b2c2 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 24 Aug 2021 14:16:41 +0200 Subject: [PATCH 331/429] Update javascript/ql/src/semmle/javascript/frameworks/Templating.qll Co-authored-by: Erik Krogh Kristensen --- .../ql/src/semmle/javascript/frameworks/Templating.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 400901b33ee..1e3a9efc729 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -630,7 +630,10 @@ module Templating { override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } - /** The `include` function, seen as an API node, so we can treat it as a template instantiation. */ + /** + * The `include` function, seen as an API node, so we can treat it as a template instantiation. + * These API nodes are used in the `getTemplateInput` predicate. + */``` private class IncludeFunctionAsEntryPoint extends API::EntryPoint { IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" } From 8a564cc64bbb3a7715b425568dd5cd64389daa62 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 24 Aug 2021 14:31:00 +0200 Subject: [PATCH 332/429] JS: Fix qldoc --- .../ql/src/semmle/javascript/frameworks/Templating.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 1e3a9efc729..49b1dc46a86 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -631,9 +631,11 @@ module Templating { } /** - * The `include` function, seen as an API node, so we can treat it as a template instantiation. + * The `include` function, seen as an API node, so we can treat it as a template instantiation + * in `EjsIncludeCallInTemplate`. + * * These API nodes are used in the `getTemplateInput` predicate. - */``` + */ private class IncludeFunctionAsEntryPoint extends API::EntryPoint { IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" } From c8d98ae649fd5d292b43815f095b25a7948c1361 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 14 Aug 2021 22:54:25 +0200 Subject: [PATCH 333/429] Java: Fix Field.getInitializer() matching non-initializer assignments --- java/ql/lib/semmle/code/java/Member.qll | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index cd3be71bea7..94dfdc9b3cc 100755 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -600,12 +600,13 @@ class Field extends Member, ExprParent, @field, Variable { /** Gets the initializer expression of this field, if any. */ override Expr getInitializer() { - exists(AssignExpr e, InitializerMethod im | + exists(AssignExpr e, InitializerMethod im, ExprStmt exprStmt | e.getDest() = this.getAnAccess() and e.getSource() = result and - pragma[only_bind_out](result).getEnclosingCallable() = im and - // This rules out updates in explicit initializer blocks as they are nested inside the compiler generated initializer blocks. - pragma[only_bind_out](e.getEnclosingStmt().getParent()) = pragma[only_bind_out](im.getBody()) + exprStmt.getExpr() = e and + // This check also rules out assignments in explicit initializer blocks + // (CodeQL models explicit initializer blocks as BlockStmt in initializer methods) + exprStmt.getParent() = im.getBody() ) } From 5a2dfda09ea88b0d2652a201bf6bc958b0a4fdb0 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Aug 2021 14:02:53 +0100 Subject: [PATCH 334/429] Add test for field initializers --- .../library-tests/fields/FieldDecl.expected | 4 +++ .../fields/FieldDeclLocation.expected | 4 +++ .../fields/FieldInitializers.expected | 6 +++++ .../library-tests/fields/FieldInitializers.ql | 4 +++ .../fields/FieldLocation.expected | 4 +++ .../library-tests/fields/PrintAst.expected | 26 +++++++++++++++++++ .../fields/fields/FieldTest.java | 10 +++++++ 7 files changed, 58 insertions(+) create mode 100644 java/ql/test/library-tests/fields/FieldInitializers.expected create mode 100644 java/ql/test/library-tests/fields/FieldInitializers.ql diff --git a/java/ql/test/library-tests/fields/FieldDecl.expected b/java/ql/test/library-tests/fields/FieldDecl.expected index 593808f58e4..edc8c0f6a1b 100644 --- a/java/ql/test/library-tests/fields/FieldDecl.expected +++ b/java/ql/test/library-tests/fields/FieldDecl.expected @@ -5,3 +5,7 @@ | fields/FieldTest.java:5:9:5:39 | Object obj, ...; | 1/2 | fields/FieldTest.java:5:35:5:38 | obj2 | | fields/FieldTest.java:6:9:6:58 | List<> l, ...; | 0/2 | fields/FieldTest.java:6:54:6:54 | l | | fields/FieldTest.java:6:9:6:58 | List<> l, ...; | 1/2 | fields/FieldTest.java:6:57:6:57 | m | +| fields/FieldTest.java:7:9:7:18 | int x, ...; | 0/1 | fields/FieldTest.java:7:13:7:13 | x | +| fields/FieldTest.java:8:9:8:22 | int y, ...; | 0/1 | fields/FieldTest.java:8:13:8:13 | y | +| fields/FieldTest.java:12:9:12:25 | int z, ...; | 0/1 | fields/FieldTest.java:12:20:12:20 | z | +| fields/FieldTest.java:13:9:13:29 | int w, ...; | 0/1 | fields/FieldTest.java:13:20:13:20 | w | diff --git a/java/ql/test/library-tests/fields/FieldDeclLocation.expected b/java/ql/test/library-tests/fields/FieldDeclLocation.expected index 951a3166ef5..53e5fb2f8b5 100644 --- a/java/ql/test/library-tests/fields/FieldDeclLocation.expected +++ b/java/ql/test/library-tests/fields/FieldDeclLocation.expected @@ -1,3 +1,7 @@ | List<> l, ...; | 6 | 9 | 6 | 58 | | Object obj, ...; | 5 | 9 | 5 | 39 | | float ff, ...; | 4 | 9 | 4 | 32 | +| int w, ...; | 13 | 9 | 13 | 29 | +| int x, ...; | 7 | 9 | 7 | 18 | +| int y, ...; | 8 | 9 | 8 | 22 | +| int z, ...; | 12 | 9 | 12 | 25 | diff --git a/java/ql/test/library-tests/fields/FieldInitializers.expected b/java/ql/test/library-tests/fields/FieldInitializers.expected new file mode 100644 index 00000000000..9047dc42d5e --- /dev/null +++ b/java/ql/test/library-tests/fields/FieldInitializers.expected @@ -0,0 +1,6 @@ +| fields/FieldTest.java:4:19:4:19 | g | fields/FieldTest.java:4:23:4:26 | 2.3f | +| fields/FieldTest.java:5:23:5:25 | obj | fields/FieldTest.java:5:29:5:32 | null | +| fields/FieldTest.java:7:13:7:13 | x | fields/FieldTest.java:7:17:7:17 | 0 | +| fields/FieldTest.java:8:13:8:13 | y | fields/FieldTest.java:8:17:8:21 | ...=... | +| fields/FieldTest.java:12:20:12:20 | z | fields/FieldTest.java:12:24:12:24 | 0 | +| fields/FieldTest.java:13:20:13:20 | w | fields/FieldTest.java:13:24:13:28 | ...=... | diff --git a/java/ql/test/library-tests/fields/FieldInitializers.ql b/java/ql/test/library-tests/fields/FieldInitializers.ql new file mode 100644 index 00000000000..b7354c2ead4 --- /dev/null +++ b/java/ql/test/library-tests/fields/FieldInitializers.ql @@ -0,0 +1,4 @@ +import java + +from Field f +select f, f.getInitializer() diff --git a/java/ql/test/library-tests/fields/FieldLocation.expected b/java/ql/test/library-tests/fields/FieldLocation.expected index 361fb1ad51a..d9fb41fd8b0 100644 --- a/java/ql/test/library-tests/fields/FieldLocation.expected +++ b/java/ql/test/library-tests/fields/FieldLocation.expected @@ -5,3 +5,7 @@ | fields/FieldTest.java:5:35:5:38 | obj2 | 5 | 35 | 5 | 38 | | fields/FieldTest.java:6:54:6:54 | l | 6 | 54 | 6 | 54 | | fields/FieldTest.java:6:57:6:57 | m | 6 | 57 | 6 | 57 | +| fields/FieldTest.java:7:13:7:13 | x | 7 | 13 | 7 | 13 | +| fields/FieldTest.java:8:13:8:13 | y | 8 | 13 | 8 | 13 | +| fields/FieldTest.java:12:20:12:20 | z | 12 | 20 | 12 | 20 | +| fields/FieldTest.java:13:20:13:20 | w | 13 | 20 | 13 | 20 | diff --git a/java/ql/test/library-tests/fields/PrintAst.expected b/java/ql/test/library-tests/fields/PrintAst.expected index 60f8a7fee45..e0ba17d7403 100644 --- a/java/ql/test/library-tests/fields/PrintAst.expected +++ b/java/ql/test/library-tests/fields/PrintAst.expected @@ -12,3 +12,29 @@ fields/FieldTest.java: # 6| 1: [Annotation] SuppressWarnings # 6| 1: [StringLiteral] "rawtypes" # 6| -1: [TypeAccess] List<> +# 7| 7: [FieldDeclaration] int x, ...; +# 7| -1: [TypeAccess] int +# 7| 0: [IntegerLiteral] 0 +# 8| 8: [FieldDeclaration] int y, ...; +# 8| -1: [TypeAccess] int +# 8| 0: [AssignExpr] ...=... +# 8| 0: [VarAccess] x +# 8| 1: [IntegerLiteral] 1 +# 9| 9: [BlockStmt] { ... } +# 10| 0: [ExprStmt] ; +# 10| 0: [AssignExpr] ...=... +# 10| 0: [VarAccess] x +# 10| 1: [IntegerLiteral] 2 +# 12| 10: [FieldDeclaration] int z, ...; +# 12| -1: [TypeAccess] int +# 12| 0: [IntegerLiteral] 0 +# 13| 11: [FieldDeclaration] int w, ...; +# 13| -1: [TypeAccess] int +# 13| 0: [AssignExpr] ...=... +# 13| 0: [VarAccess] z +# 13| 1: [IntegerLiteral] 1 +# 14| 12: [BlockStmt] { ... } +# 15| 0: [ExprStmt] ; +# 15| 0: [AssignExpr] ...=... +# 15| 0: [VarAccess] z +# 15| 1: [IntegerLiteral] 2 diff --git a/java/ql/test/library-tests/fields/fields/FieldTest.java b/java/ql/test/library-tests/fields/fields/FieldTest.java index 3916b7c75c2..756c6e0d9ff 100644 --- a/java/ql/test/library-tests/fields/fields/FieldTest.java +++ b/java/ql/test/library-tests/fields/fields/FieldTest.java @@ -4,4 +4,14 @@ public class FieldTest { float ff, g = 2.3f, hhh; static Object obj = null, obj2; @SuppressWarnings("rawtypes") java.util.List l, m; + int x = 0; + int y = x = 1; + { + x = 2; // Shouldn't show up as an initializer + } + static int z = 0; + static int w = z = 1; + static { + z = 2; // Shouldn't show up as an initializer + } } From 19ee64d9adba351a535529341bf91601b03d8cc8 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 24 Aug 2021 17:14:42 +0200 Subject: [PATCH 335/429] C++:Lower potentially-dangerous-function precision There have been multiple reports of false positives from this query over time. Now that it has `@security-severity 10.0`, these false positives look even worse. The query looks purely for calls to functions with certain names, not at whether the calls happen in a dangerous context. To justify a higher precision, the query should only flag calls that happen in a thread or another non-reentrant context. --- cpp/change-notes/2021-08-23-ctime-weaken-claims.md | 2 ++ .../src/Security/CWE/CWE-676/PotentiallyDangerousFunction.qhelp | 2 +- cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 cpp/change-notes/2021-08-23-ctime-weaken-claims.md diff --git a/cpp/change-notes/2021-08-23-ctime-weaken-claims.md b/cpp/change-notes/2021-08-23-ctime-weaken-claims.md new file mode 100644 index 00000000000..a26e074c8db --- /dev/null +++ b/cpp/change-notes/2021-08-23-ctime-weaken-claims.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* Lowered the precision of `cpp/potentially-dangerous-function` so it is run but not displayed on LGTM by default and so it's only run and displayed on Code Scanning if a broader suite like `cpp-security-extended` is opted into. diff --git a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.qhelp b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.qhelp index d3dd40df132..55fc7dcb722 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.qhelp @@ -26,7 +26,7 @@ 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.

    +asctime_r (if those functions exist on your platform).

    diff --git a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql index 4e281b238bc..a77c3ce7a1e 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql @@ -4,7 +4,7 @@ * @kind problem * @problem.severity warning * @security-severity 10.0 - * @precision high + * @precision medium * @id cpp/potentially-dangerous-function * @tags reliability * security From 7f3066cd64d6b92a3a5f37a6f6781f1311309fd3 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 24 Aug 2021 13:01:02 -0700 Subject: [PATCH 336/429] Java: Move the ExternalArtifact.qll module to the library pack --- java/ql/{src => lib}/external/ExternalArtifact.qll | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename java/ql/{src => lib}/external/ExternalArtifact.qll (100%) diff --git a/java/ql/src/external/ExternalArtifact.qll b/java/ql/lib/external/ExternalArtifact.qll similarity index 100% rename from java/ql/src/external/ExternalArtifact.qll rename to java/ql/lib/external/ExternalArtifact.qll From 3660c64328fd8277d80af24eb0a3370bb2be8851 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 24 Aug 2021 13:17:49 -0700 Subject: [PATCH 337/429] Packaging: Rafactor Python core libraries Extract the external facing `qll` files into the codeql/python-all query pack. --- misc/legacy-support/python/qlpack.yml | 2 +- python/ql/examples/qlpack.lock.yml | 4 ++++ python/ql/examples/qlpack.yml | 4 ++-- python/ql/{src => lib}/Customizations.qll | 0 python/ql/{src => lib}/default.qll | 0 python/ql/{src => lib}/python.qll | 0 python/ql/lib/qlpack.lock.yml | 4 ++++ python/ql/lib/qlpack.yml | 7 +++++++ python/ql/{src => lib}/semmle/crypto/Crypto.qll | 0 python/ql/{src => lib}/semmle/dataflow/SSA.qll | 0 python/ql/{src => lib}/semmle/files/FileSystem.qll | 0 python/ql/{src => lib}/semmle/python/ApiGraphs.qll | 0 python/ql/{src => lib}/semmle/python/AstExtended.qll | 0 python/ql/{src => lib}/semmle/python/AstGenerated.qll | 0 python/ql/{src => lib}/semmle/python/Class.qll | 0 python/ql/{src => lib}/semmle/python/Comment.qll | 0 python/ql/{src => lib}/semmle/python/Comparisons.qll | 0 python/ql/{src => lib}/semmle/python/Comprehensions.qll | 0 python/ql/{src => lib}/semmle/python/Concepts.qll | 0 python/ql/{src => lib}/semmle/python/Constants.qll | 0 python/ql/{src => lib}/semmle/python/Exprs.qll | 0 python/ql/{src => lib}/semmle/python/Files.qll | 0 python/ql/{src => lib}/semmle/python/Flow.qll | 0 python/ql/{src => lib}/semmle/python/Frameworks.qll | 0 python/ql/{src => lib}/semmle/python/Function.qll | 0 .../ql/{src => lib}/semmle/python/GuardedControlFlow.qll | 0 python/ql/{src => lib}/semmle/python/Import.qll | 0 python/ql/{src => lib}/semmle/python/Keywords.qll | 0 python/ql/{src => lib}/semmle/python/Metrics.qll | 0 python/ql/{src => lib}/semmle/python/Module.qll | 0 python/ql/{src => lib}/semmle/python/Operations.qll | 0 python/ql/{src => lib}/semmle/python/PrintAst.qll | 0 python/ql/{src => lib}/semmle/python/RegexTreeView.qll | 0 python/ql/{src => lib}/semmle/python/SSA.qll | 0 python/ql/{src => lib}/semmle/python/Scope.qll | 0 python/ql/{src => lib}/semmle/python/SelfAttribute.qll | 0 python/ql/{src => lib}/semmle/python/SpecialMethods.qll | 0 python/ql/{src => lib}/semmle/python/Stmts.qll | 0 python/ql/{src => lib}/semmle/python/TestUtils.qll | 0 python/ql/{src => lib}/semmle/python/Unit.qll | 0 python/ql/{src => lib}/semmle/python/Variables.qll | 0 .../semmle/python/concepts/CryptoAlgorithms.qll | 0 .../semmle/python/dataflow/Configuration.qll | 0 .../ql/{src => lib}/semmle/python/dataflow/DataFlow.qll | 0 python/ql/{src => lib}/semmle/python/dataflow/Files.qll | 0 .../semmle/python/dataflow/Implementation.qll | 0 python/ql/{src => lib}/semmle/python/dataflow/Legacy.qll | 0 .../semmle/python/dataflow/StateTracking.qll | 0 .../semmle/python/dataflow/TaintTracking.qll | 0 .../semmle/python/dataflow/new/BarrierGuards.qll | 0 .../{src => lib}/semmle/python/dataflow/new/DataFlow.qll | 0 .../semmle/python/dataflow/new/DataFlow2.qll | 0 .../semmle/python/dataflow/new/DataFlow3.qll | 0 .../semmle/python/dataflow/new/DataFlow4.qll | 0 .../semmle/python/dataflow/new/RemoteFlowSources.qll | 0 .../semmle/python/dataflow/new/SensitiveDataSources.qll | 0 .../semmle/python/dataflow/new/TaintTracking.qll | 0 .../semmle/python/dataflow/new/TaintTracking2.qll | 0 .../semmle/python/dataflow/new/TaintTracking3.qll | 0 .../semmle/python/dataflow/new/TaintTracking4.qll | 0 .../semmle/python/dataflow/new/TypeTracker.qll | 0 .../semmle/python/dataflow/new/internal/Attributes.qll | 0 .../semmle/python/dataflow/new/internal/DataFlowImpl.qll | 0 .../python/dataflow/new/internal/DataFlowImpl2.qll | 0 .../python/dataflow/new/internal/DataFlowImpl3.qll | 0 .../python/dataflow/new/internal/DataFlowImpl4.qll | 0 .../python/dataflow/new/internal/DataFlowImplCommon.qll | 0 .../dataflow/new/internal/DataFlowImplConsistency.qll | 0 .../dataflow/new/internal/DataFlowImplSpecific.qll | 0 .../python/dataflow/new/internal/DataFlowPrivate.qll | 0 .../python/dataflow/new/internal/DataFlowPublic.qll | 0 .../semmle/python/dataflow/new/internal/DataFlowUtil.qll | 0 .../semmle/python/dataflow/new/internal/LocalSources.qll | 0 .../dataflow/new/internal/TaintTrackingPrivate.qll | 0 .../python/dataflow/new/internal/TaintTrackingPublic.qll | 0 .../semmle/python/dataflow/new/internal/TypeTracker.qll | 0 .../python/dataflow/new/internal/TypeTrackerSpecific.qll | 0 .../semmle/python/dataflow/new/internal/readme.md | 0 .../new/internal/tainttracking1/TaintTrackingImpl.qll | 0 .../internal/tainttracking1/TaintTrackingParameter.qll | 0 .../new/internal/tainttracking2/TaintTrackingImpl.qll | 0 .../internal/tainttracking2/TaintTrackingParameter.qll | 0 .../new/internal/tainttracking3/TaintTrackingImpl.qll | 0 .../internal/tainttracking3/TaintTrackingParameter.qll | 0 .../new/internal/tainttracking4/TaintTrackingImpl.qll | 0 .../internal/tainttracking4/TaintTrackingParameter.qll | 0 .../semmle/python/dataflow/old/Configuration.qll | 0 .../{src => lib}/semmle/python/dataflow/old/DataFlow.qll | 0 .../ql/{src => lib}/semmle/python/dataflow/old/Files.qll | 0 .../semmle/python/dataflow/old/Implementation.qll | 0 .../{src => lib}/semmle/python/dataflow/old/Legacy.qll | 0 .../semmle/python/dataflow/old/StateTracking.qll | 0 .../semmle/python/dataflow/old/TaintTracking.qll | 0 .../semmle/python/dependencies/Dependencies.qll | 0 .../semmle/python/dependencies/DependencyKind.qll | 0 .../semmle/python/dependencies/TechInventory.qll | 0 .../ql/{src => lib}/semmle/python/essa/Definitions.qll | 0 python/ql/{src => lib}/semmle/python/essa/Essa.qll | 0 python/ql/{src => lib}/semmle/python/essa/SsaCompute.qll | 0 .../{src => lib}/semmle/python/essa/SsaDefinitions.qll | 0 .../{src => lib}/semmle/python/filters/GeneratedCode.qll | 0 python/ql/{src => lib}/semmle/python/filters/Tests.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Aioch.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Aiohttp.qll | 0 .../semmle/python/frameworks/ClickhouseDriver.qll | 0 .../{src => lib}/semmle/python/frameworks/Cryptodome.qll | 0 .../semmle/python/frameworks/Cryptography.qll | 0 python/ql/{src => lib}/semmle/python/frameworks/Dill.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Django.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Fabric.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Flask.qll | 0 python/ql/{src => lib}/semmle/python/frameworks/Idna.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Invoke.qll | 0 .../{src => lib}/semmle/python/frameworks/Jmespath.qll | 0 .../{src => lib}/semmle/python/frameworks/MarkupSafe.qll | 0 .../{src => lib}/semmle/python/frameworks/Multidict.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/MySQLdb.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Mysql.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/PEP249.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Peewee.qll | 0 .../{src => lib}/semmle/python/frameworks/Psycopg2.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/PyMySQL.qll | 0 python/ql/{src => lib}/semmle/python/frameworks/Rsa.qll | 0 .../{src => lib}/semmle/python/frameworks/Simplejson.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Stdlib.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Tornado.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Twisted.qll | 0 .../ql/{src => lib}/semmle/python/frameworks/Ujson.qll | 0 .../{src => lib}/semmle/python/frameworks/Werkzeug.qll | 0 python/ql/{src => lib}/semmle/python/frameworks/Yaml.qll | 0 python/ql/{src => lib}/semmle/python/frameworks/Yarl.qll | 0 .../semmle/python/frameworks/internal/PEP249Impl.qll | 0 .../frameworks/internal/PoorMansFunctionResolution.qll | 0 .../semmle/python/frameworks/internal/SelfRefMixin.qll | 0 python/ql/{src => lib}/semmle/python/libraries/Zope.qll | 0 .../ql/{src => lib}/semmle/python/objects/Callables.qll | 0 python/ql/{src => lib}/semmle/python/objects/Classes.qll | 0 .../ql/{src => lib}/semmle/python/objects/Constants.qll | 0 .../{src => lib}/semmle/python/objects/Descriptors.qll | 0 .../ql/{src => lib}/semmle/python/objects/Instances.qll | 0 python/ql/{src => lib}/semmle/python/objects/Modules.qll | 0 .../ql/{src => lib}/semmle/python/objects/ObjectAPI.qll | 0 .../semmle/python/objects/ObjectInternal.qll | 0 .../ql/{src => lib}/semmle/python/objects/ObjectModel.md | 0 .../ql/{src => lib}/semmle/python/objects/Sequences.qll | 0 python/ql/{src => lib}/semmle/python/objects/TObject.qll | 0 python/ql/{src => lib}/semmle/python/pointsto/Base.qll | 0 .../ql/{src => lib}/semmle/python/pointsto/CallGraph.qll | 0 .../ql/{src => lib}/semmle/python/pointsto/Context.qll | 0 .../ql/{src => lib}/semmle/python/pointsto/Filters.qll | 0 python/ql/{src => lib}/semmle/python/pointsto/Final.qll | 0 python/ql/{src => lib}/semmle/python/pointsto/MRO.qll | 0 .../ql/{src => lib}/semmle/python/pointsto/Overview.qll | 0 .../ql/{src => lib}/semmle/python/pointsto/PointsTo.qll | 0 .../semmle/python/pointsto/PointsToContext.qll | 0 python/ql/{src => lib}/semmle/python/protocols.qll | 0 python/ql/{src => lib}/semmle/python/regex.qll | 0 .../ql/{src => lib}/semmle/python/security/ClearText.qll | 0 python/ql/{src => lib}/semmle/python/security/Crypto.qll | 0 .../{src => lib}/semmle/python/security/Exceptions.qll | 0 python/ql/{src => lib}/semmle/python/security/Paths.qll | 0 python/ql/{src => lib}/semmle/python/security/README.md | 0 python/ql/{src => lib}/semmle/python/security/SQL.qll | 0 .../semmle/python/security/SensitiveData.qll | 0 .../semmle/python/security/TaintTracking.qll | 0 .../semmle/python/security/dataflow/ChainedConfigs12.qll | 0 .../semmle/python/security/dataflow/CleartextLogging.qll | 0 .../security/dataflow/CleartextLoggingCustomizations.qll | 0 .../semmle/python/security/dataflow/CleartextStorage.qll | 0 .../security/dataflow/CleartextStorageCustomizations.qll | 0 .../semmle/python/security/dataflow/CodeInjection.qll | 0 .../security/dataflow/CodeInjectionCustomizations.qll | 0 .../semmle/python/security/dataflow/CommandInjection.qll | 0 .../security/dataflow/CommandInjectionCustomizations.qll | 0 .../semmle/python/security/dataflow/ExceptionInfo.qll | 0 .../semmle/python/security/dataflow/PathInjection.qll | 0 .../security/dataflow/PathInjectionCustomizations.qll | 0 .../semmle/python/security/dataflow/PolynomialReDoS.qll | 0 .../security/dataflow/PolynomialReDoSCustomizations.qll | 0 .../semmle/python/security/dataflow/ReflectedXSS.qll | 0 .../security/dataflow/ReflectedXSSCustomizations.qll | 0 .../semmle/python/security/dataflow/SqlInjection.qll | 0 .../security/dataflow/SqlInjectionCustomizations.qll | 0 .../python/security/dataflow/StackTraceExposure.qll | 0 .../dataflow/StackTraceExposureCustomizations.qll | 0 .../python/security/dataflow/UnsafeDeserialization.qll | 0 .../dataflow/UnsafeDeserializationCustomizations.qll | 0 .../semmle/python/security/dataflow/UrlRedirect.qll | 0 .../security/dataflow/UrlRedirectCustomizations.qll | 0 .../security/dataflow/WeakSensitiveDataHashing.qll | 0 .../dataflow/WeakSensitiveDataHashingCustomizations.qll | 0 .../{src => lib}/semmle/python/security/flow/AnyCall.qll | 0 .../semmle/python/security/injection/Command.qll | 0 .../semmle/python/security/injection/Deserialization.qll | 0 .../semmle/python/security/injection/Exec.qll | 0 .../semmle/python/security/injection/Marshal.qll | 0 .../semmle/python/security/injection/Path.qll | 0 .../semmle/python/security/injection/Pickle.qll | 0 .../semmle/python/security/injection/Sql.qll | 0 .../semmle/python/security/injection/Xml.qll | 0 .../semmle/python/security/injection/Yaml.qll | 0 .../python/security/internal/SensitiveDataHeuristics.qll | 0 .../security/performance/ExponentialBackTracking.qll | 0 .../semmle/python/security/performance/ReDoSUtil.qll | 0 .../python/security/performance/RegExpTreeView.qll | 0 .../security/performance/SuperlinearBackTracking.qll | 0 .../semmle/python/security/strings/Basic.qll | 0 .../semmle/python/security/strings/Common.qll | 0 .../semmle/python/security/strings/External.qll | 0 .../semmle/python/security/strings/Untrusted.qll | 0 python/ql/{src => lib}/semmle/python/strings.qll | 0 .../ql/{src => lib}/semmle/python/templates/PyxlTags.qll | 0 .../{src => lib}/semmle/python/templates/Templates.qll | 0 python/ql/{src => lib}/semmle/python/types/Builtins.qll | 0 .../ql/{src => lib}/semmle/python/types/ClassObject.qll | 0 .../ql/{src => lib}/semmle/python/types/Descriptors.qll | 0 .../ql/{src => lib}/semmle/python/types/Exceptions.qll | 0 .../ql/{src => lib}/semmle/python/types/Extensions.qll | 0 .../{src => lib}/semmle/python/types/FunctionObject.qll | 0 .../semmle/python/types/IgnoredAndApproximations.txt | 0 .../ql/{src => lib}/semmle/python/types/ImportTime.qll | 0 .../ql/{src => lib}/semmle/python/types/ModuleKind.qll | 0 .../ql/{src => lib}/semmle/python/types/ModuleObject.qll | 0 python/ql/{src => lib}/semmle/python/types/Object.qll | 0 .../ql/{src => lib}/semmle/python/types/Properties.qll | 0 python/ql/{src => lib}/semmle/python/types/Version.qll | 0 .../semmle/python/values/StringAttributes.qll | 0 .../{src => lib}/semmle/python/web/ClientHttpRequest.qll | 0 python/ql/{src => lib}/semmle/python/web/Http.qll | 0 .../ql/{src => lib}/semmle/python/web/HttpConstants.qll | 0 .../ql/{src => lib}/semmle/python/web/HttpRedirect.qll | 0 python/ql/{src => lib}/semmle/python/web/HttpRequest.qll | 0 .../ql/{src => lib}/semmle/python/web/HttpResponse.qll | 0 .../ql/{src => lib}/semmle/python/web/bottle/General.qll | 0 .../{src => lib}/semmle/python/web/bottle/Redirect.qll | 0 .../ql/{src => lib}/semmle/python/web/bottle/Request.qll | 0 .../{src => lib}/semmle/python/web/bottle/Response.qll | 0 .../{src => lib}/semmle/python/web/cherrypy/General.qll | 0 .../{src => lib}/semmle/python/web/cherrypy/Request.qll | 0 .../{src => lib}/semmle/python/web/cherrypy/Response.qll | 0 .../{src => lib}/semmle/python/web/client/Requests.qll | 0 .../ql/{src => lib}/semmle/python/web/client/StdLib.qll | 0 python/ql/{src => lib}/semmle/python/web/django/Db.qll | 0 .../ql/{src => lib}/semmle/python/web/django/General.qll | 0 .../ql/{src => lib}/semmle/python/web/django/Model.qll | 0 .../{src => lib}/semmle/python/web/django/Redirect.qll | 0 .../ql/{src => lib}/semmle/python/web/django/Request.qll | 0 .../{src => lib}/semmle/python/web/django/Response.qll | 0 .../{src => lib}/semmle/python/web/django/Sanitizers.qll | 0 .../ql/{src => lib}/semmle/python/web/django/Shared.qll | 0 .../ql/{src => lib}/semmle/python/web/falcon/General.qll | 0 .../ql/{src => lib}/semmle/python/web/falcon/Request.qll | 0 .../{src => lib}/semmle/python/web/falcon/Response.qll | 0 .../ql/{src => lib}/semmle/python/web/flask/General.qll | 0 .../ql/{src => lib}/semmle/python/web/flask/Redirect.qll | 0 .../ql/{src => lib}/semmle/python/web/flask/Request.qll | 0 .../ql/{src => lib}/semmle/python/web/flask/Response.qll | 0 .../{src => lib}/semmle/python/web/pyramid/Redirect.qll | 0 .../{src => lib}/semmle/python/web/pyramid/Request.qll | 0 .../{src => lib}/semmle/python/web/pyramid/Response.qll | 0 .../ql/{src => lib}/semmle/python/web/pyramid/View.qll | 0 .../ql/{src => lib}/semmle/python/web/stdlib/Request.qll | 0 .../{src => lib}/semmle/python/web/stdlib/Response.qll | 0 .../{src => lib}/semmle/python/web/tornado/Redirect.qll | 0 .../{src => lib}/semmle/python/web/tornado/Request.qll | 0 .../{src => lib}/semmle/python/web/tornado/Response.qll | 0 .../{src => lib}/semmle/python/web/tornado/Tornado.qll | 0 .../semmle/python/web/turbogears/Request.qll | 0 .../semmle/python/web/turbogears/Response.qll | 0 .../semmle/python/web/turbogears/TurboGears.qll | 0 .../{src => lib}/semmle/python/web/twisted/Request.qll | 0 .../{src => lib}/semmle/python/web/twisted/Response.qll | 0 .../{src => lib}/semmle/python/web/twisted/Twisted.qll | 0 .../ql/{src => lib}/semmle/python/web/webob/Request.qll | 0 python/ql/{src => lib}/semmle/python/xml/XML.qll | 0 python/ql/{src => lib}/semmlecode.python.dbscheme | 0 python/ql/{src => lib}/semmlecode.python.dbscheme.stats | 0 python/ql/{src => lib}/site.qll | 0 python/ql/src/codeql-suites/python-code-scanning.qls | 2 +- python/ql/src/codeql-suites/python-lgtm-full.qls | 2 +- .../ql/src/codeql-suites/python-security-and-quality.qls | 2 +- python/ql/src/codeql-suites/python-security-extended.qls | 2 +- python/ql/src/qlpack.lock.yml | 4 ++++ python/ql/src/qlpack.yml | 9 ++++++--- python/ql/test/qlpack.lock.yml | 4 ++++ python/ql/test/qlpack.yml | 6 ++++-- python/upgrades/qlpack.lock.yml | 4 ++++ python/upgrades/qlpack.yml | 4 +++- 288 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 python/ql/examples/qlpack.lock.yml rename python/ql/{src => lib}/Customizations.qll (100%) rename python/ql/{src => lib}/default.qll (100%) rename python/ql/{src => lib}/python.qll (100%) create mode 100644 python/ql/lib/qlpack.lock.yml create mode 100644 python/ql/lib/qlpack.yml rename python/ql/{src => lib}/semmle/crypto/Crypto.qll (100%) rename python/ql/{src => lib}/semmle/dataflow/SSA.qll (100%) rename python/ql/{src => lib}/semmle/files/FileSystem.qll (100%) rename python/ql/{src => lib}/semmle/python/ApiGraphs.qll (100%) rename python/ql/{src => lib}/semmle/python/AstExtended.qll (100%) rename python/ql/{src => lib}/semmle/python/AstGenerated.qll (100%) rename python/ql/{src => lib}/semmle/python/Class.qll (100%) rename python/ql/{src => lib}/semmle/python/Comment.qll (100%) rename python/ql/{src => lib}/semmle/python/Comparisons.qll (100%) rename python/ql/{src => lib}/semmle/python/Comprehensions.qll (100%) rename python/ql/{src => lib}/semmle/python/Concepts.qll (100%) rename python/ql/{src => lib}/semmle/python/Constants.qll (100%) rename python/ql/{src => lib}/semmle/python/Exprs.qll (100%) rename python/ql/{src => lib}/semmle/python/Files.qll (100%) rename python/ql/{src => lib}/semmle/python/Flow.qll (100%) rename python/ql/{src => lib}/semmle/python/Frameworks.qll (100%) rename python/ql/{src => lib}/semmle/python/Function.qll (100%) rename python/ql/{src => lib}/semmle/python/GuardedControlFlow.qll (100%) rename python/ql/{src => lib}/semmle/python/Import.qll (100%) rename python/ql/{src => lib}/semmle/python/Keywords.qll (100%) rename python/ql/{src => lib}/semmle/python/Metrics.qll (100%) rename python/ql/{src => lib}/semmle/python/Module.qll (100%) rename python/ql/{src => lib}/semmle/python/Operations.qll (100%) rename python/ql/{src => lib}/semmle/python/PrintAst.qll (100%) rename python/ql/{src => lib}/semmle/python/RegexTreeView.qll (100%) rename python/ql/{src => lib}/semmle/python/SSA.qll (100%) rename python/ql/{src => lib}/semmle/python/Scope.qll (100%) rename python/ql/{src => lib}/semmle/python/SelfAttribute.qll (100%) rename python/ql/{src => lib}/semmle/python/SpecialMethods.qll (100%) rename python/ql/{src => lib}/semmle/python/Stmts.qll (100%) rename python/ql/{src => lib}/semmle/python/TestUtils.qll (100%) rename python/ql/{src => lib}/semmle/python/Unit.qll (100%) rename python/ql/{src => lib}/semmle/python/Variables.qll (100%) rename python/ql/{src => lib}/semmle/python/concepts/CryptoAlgorithms.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/Configuration.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/DataFlow.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/Files.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/Implementation.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/Legacy.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/StateTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/TaintTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/BarrierGuards.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/DataFlow.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/DataFlow2.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/DataFlow3.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/DataFlow4.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/RemoteFlowSources.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/SensitiveDataSources.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/TaintTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/TaintTracking2.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/TaintTracking3.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/TaintTracking4.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/TypeTracker.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/Attributes.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImpl.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImpl2.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImpl3.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImpl4.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowPrivate.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowPublic.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/DataFlowUtil.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/LocalSources.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/TypeTracker.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/readme.md (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingParameter.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingParameter.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingParameter.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingParameter.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/Configuration.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/DataFlow.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/Files.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/Implementation.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/Legacy.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/StateTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/dataflow/old/TaintTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/dependencies/Dependencies.qll (100%) rename python/ql/{src => lib}/semmle/python/dependencies/DependencyKind.qll (100%) rename python/ql/{src => lib}/semmle/python/dependencies/TechInventory.qll (100%) rename python/ql/{src => lib}/semmle/python/essa/Definitions.qll (100%) rename python/ql/{src => lib}/semmle/python/essa/Essa.qll (100%) rename python/ql/{src => lib}/semmle/python/essa/SsaCompute.qll (100%) rename python/ql/{src => lib}/semmle/python/essa/SsaDefinitions.qll (100%) rename python/ql/{src => lib}/semmle/python/filters/GeneratedCode.qll (100%) rename python/ql/{src => lib}/semmle/python/filters/Tests.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Aioch.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Aiohttp.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/ClickhouseDriver.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Cryptodome.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Cryptography.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Dill.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Django.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Fabric.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Flask.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Idna.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Invoke.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Jmespath.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/MarkupSafe.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Multidict.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/MySQLdb.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Mysql.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/PEP249.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Peewee.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Psycopg2.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/PyMySQL.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Rsa.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Simplejson.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Stdlib.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Tornado.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Twisted.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Ujson.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Werkzeug.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Yaml.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/Yarl.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/internal/PEP249Impl.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll (100%) rename python/ql/{src => lib}/semmle/python/frameworks/internal/SelfRefMixin.qll (100%) rename python/ql/{src => lib}/semmle/python/libraries/Zope.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Callables.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Classes.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Constants.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Descriptors.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Instances.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/Modules.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/ObjectAPI.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/ObjectInternal.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/ObjectModel.md (100%) rename python/ql/{src => lib}/semmle/python/objects/Sequences.qll (100%) rename python/ql/{src => lib}/semmle/python/objects/TObject.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/Base.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/CallGraph.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/Context.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/Filters.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/Final.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/MRO.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/Overview.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/PointsTo.qll (100%) rename python/ql/{src => lib}/semmle/python/pointsto/PointsToContext.qll (100%) rename python/ql/{src => lib}/semmle/python/protocols.qll (100%) rename python/ql/{src => lib}/semmle/python/regex.qll (100%) rename python/ql/{src => lib}/semmle/python/security/ClearText.qll (100%) rename python/ql/{src => lib}/semmle/python/security/Crypto.qll (100%) rename python/ql/{src => lib}/semmle/python/security/Exceptions.qll (100%) rename python/ql/{src => lib}/semmle/python/security/Paths.qll (100%) rename python/ql/{src => lib}/semmle/python/security/README.md (100%) rename python/ql/{src => lib}/semmle/python/security/SQL.qll (100%) rename python/ql/{src => lib}/semmle/python/security/SensitiveData.qll (100%) rename python/ql/{src => lib}/semmle/python/security/TaintTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/ChainedConfigs12.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CleartextLogging.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CleartextStorage.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CleartextStorageCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CodeInjection.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CodeInjectionCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CommandInjection.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/CommandInjectionCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/ExceptionInfo.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/PathInjection.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/PathInjectionCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/PolynomialReDoS.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/ReflectedXSS.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/SqlInjection.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/SqlInjectionCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/StackTraceExposure.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/UnsafeDeserialization.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/UrlRedirect.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/UrlRedirectCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll (100%) rename python/ql/{src => lib}/semmle/python/security/dataflow/WeakSensitiveDataHashingCustomizations.qll (100%) rename python/ql/{src => lib}/semmle/python/security/flow/AnyCall.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Command.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Deserialization.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Exec.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Marshal.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Path.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Pickle.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Sql.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Xml.qll (100%) rename python/ql/{src => lib}/semmle/python/security/injection/Yaml.qll (100%) rename python/ql/{src => lib}/semmle/python/security/internal/SensitiveDataHeuristics.qll (100%) rename python/ql/{src => lib}/semmle/python/security/performance/ExponentialBackTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/security/performance/ReDoSUtil.qll (100%) rename python/ql/{src => lib}/semmle/python/security/performance/RegExpTreeView.qll (100%) rename python/ql/{src => lib}/semmle/python/security/performance/SuperlinearBackTracking.qll (100%) rename python/ql/{src => lib}/semmle/python/security/strings/Basic.qll (100%) rename python/ql/{src => lib}/semmle/python/security/strings/Common.qll (100%) rename python/ql/{src => lib}/semmle/python/security/strings/External.qll (100%) rename python/ql/{src => lib}/semmle/python/security/strings/Untrusted.qll (100%) rename python/ql/{src => lib}/semmle/python/strings.qll (100%) rename python/ql/{src => lib}/semmle/python/templates/PyxlTags.qll (100%) rename python/ql/{src => lib}/semmle/python/templates/Templates.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Builtins.qll (100%) rename python/ql/{src => lib}/semmle/python/types/ClassObject.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Descriptors.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Exceptions.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Extensions.qll (100%) rename python/ql/{src => lib}/semmle/python/types/FunctionObject.qll (100%) rename python/ql/{src => lib}/semmle/python/types/IgnoredAndApproximations.txt (100%) rename python/ql/{src => lib}/semmle/python/types/ImportTime.qll (100%) rename python/ql/{src => lib}/semmle/python/types/ModuleKind.qll (100%) rename python/ql/{src => lib}/semmle/python/types/ModuleObject.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Object.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Properties.qll (100%) rename python/ql/{src => lib}/semmle/python/types/Version.qll (100%) rename python/ql/{src => lib}/semmle/python/values/StringAttributes.qll (100%) rename python/ql/{src => lib}/semmle/python/web/ClientHttpRequest.qll (100%) rename python/ql/{src => lib}/semmle/python/web/Http.qll (100%) rename python/ql/{src => lib}/semmle/python/web/HttpConstants.qll (100%) rename python/ql/{src => lib}/semmle/python/web/HttpRedirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/HttpRequest.qll (100%) rename python/ql/{src => lib}/semmle/python/web/HttpResponse.qll (100%) rename python/ql/{src => lib}/semmle/python/web/bottle/General.qll (100%) rename python/ql/{src => lib}/semmle/python/web/bottle/Redirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/bottle/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/bottle/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/cherrypy/General.qll (100%) rename python/ql/{src => lib}/semmle/python/web/cherrypy/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/cherrypy/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/client/Requests.qll (100%) rename python/ql/{src => lib}/semmle/python/web/client/StdLib.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Db.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/General.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Model.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Redirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Sanitizers.qll (100%) rename python/ql/{src => lib}/semmle/python/web/django/Shared.qll (100%) rename python/ql/{src => lib}/semmle/python/web/falcon/General.qll (100%) rename python/ql/{src => lib}/semmle/python/web/falcon/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/falcon/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/flask/General.qll (100%) rename python/ql/{src => lib}/semmle/python/web/flask/Redirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/flask/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/flask/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/pyramid/Redirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/pyramid/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/pyramid/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/pyramid/View.qll (100%) rename python/ql/{src => lib}/semmle/python/web/stdlib/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/stdlib/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/tornado/Redirect.qll (100%) rename python/ql/{src => lib}/semmle/python/web/tornado/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/tornado/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/tornado/Tornado.qll (100%) rename python/ql/{src => lib}/semmle/python/web/turbogears/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/turbogears/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/turbogears/TurboGears.qll (100%) rename python/ql/{src => lib}/semmle/python/web/twisted/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/web/twisted/Response.qll (100%) rename python/ql/{src => lib}/semmle/python/web/twisted/Twisted.qll (100%) rename python/ql/{src => lib}/semmle/python/web/webob/Request.qll (100%) rename python/ql/{src => lib}/semmle/python/xml/XML.qll (100%) rename python/ql/{src => lib}/semmlecode.python.dbscheme (100%) rename python/ql/{src => lib}/semmlecode.python.dbscheme.stats (100%) rename python/ql/{src => lib}/site.qll (100%) create mode 100644 python/ql/src/qlpack.lock.yml create mode 100644 python/ql/test/qlpack.lock.yml create mode 100644 python/upgrades/qlpack.lock.yml diff --git a/misc/legacy-support/python/qlpack.yml b/misc/legacy-support/python/qlpack.yml index 59d9dba8499..133d1e4f2d7 100644 --- a/misc/legacy-support/python/qlpack.yml +++ b/misc/legacy-support/python/qlpack.yml @@ -1,4 +1,4 @@ name: legacy-libraries-python version: 0.0.0 libraryPathDependencies: - - codeql-python + - codeql/python-all diff --git a/python/ql/examples/qlpack.lock.yml b/python/ql/examples/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/python/ql/examples/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/python/ql/examples/qlpack.yml b/python/ql/examples/qlpack.yml index bccde7557ee..6c95eee6189 100644 --- a/python/ql/examples/qlpack.yml +++ b/python/ql/examples/qlpack.yml @@ -1,3 +1,3 @@ -name: codeql-python-examples +name: codeql/python-examples version: 0.0.0 -libraryPathDependencies: codeql-python +libraryPathDependencies: codeql/python-all diff --git a/python/ql/src/Customizations.qll b/python/ql/lib/Customizations.qll similarity index 100% rename from python/ql/src/Customizations.qll rename to python/ql/lib/Customizations.qll diff --git a/python/ql/src/default.qll b/python/ql/lib/default.qll similarity index 100% rename from python/ql/src/default.qll rename to python/ql/lib/default.qll diff --git a/python/ql/src/python.qll b/python/ql/lib/python.qll similarity index 100% rename from python/ql/src/python.qll rename to python/ql/lib/python.qll diff --git a/python/ql/lib/qlpack.lock.yml b/python/ql/lib/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/python/ql/lib/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml new file mode 100644 index 00000000000..f4b13be48f5 --- /dev/null +++ b/python/ql/lib/qlpack.yml @@ -0,0 +1,7 @@ +name: codeql/python-all +version: 0.0.2 +dbscheme: semmlecode.python.dbscheme +extractor: python +library: true +dependencies: + codeql/python-upgrades: ~0.0.2 diff --git a/python/ql/src/semmle/crypto/Crypto.qll b/python/ql/lib/semmle/crypto/Crypto.qll similarity index 100% rename from python/ql/src/semmle/crypto/Crypto.qll rename to python/ql/lib/semmle/crypto/Crypto.qll diff --git a/python/ql/src/semmle/dataflow/SSA.qll b/python/ql/lib/semmle/dataflow/SSA.qll similarity index 100% rename from python/ql/src/semmle/dataflow/SSA.qll rename to python/ql/lib/semmle/dataflow/SSA.qll diff --git a/python/ql/src/semmle/files/FileSystem.qll b/python/ql/lib/semmle/files/FileSystem.qll similarity index 100% rename from python/ql/src/semmle/files/FileSystem.qll rename to python/ql/lib/semmle/files/FileSystem.qll diff --git a/python/ql/src/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll similarity index 100% rename from python/ql/src/semmle/python/ApiGraphs.qll rename to python/ql/lib/semmle/python/ApiGraphs.qll diff --git a/python/ql/src/semmle/python/AstExtended.qll b/python/ql/lib/semmle/python/AstExtended.qll similarity index 100% rename from python/ql/src/semmle/python/AstExtended.qll rename to python/ql/lib/semmle/python/AstExtended.qll diff --git a/python/ql/src/semmle/python/AstGenerated.qll b/python/ql/lib/semmle/python/AstGenerated.qll similarity index 100% rename from python/ql/src/semmle/python/AstGenerated.qll rename to python/ql/lib/semmle/python/AstGenerated.qll diff --git a/python/ql/src/semmle/python/Class.qll b/python/ql/lib/semmle/python/Class.qll similarity index 100% rename from python/ql/src/semmle/python/Class.qll rename to python/ql/lib/semmle/python/Class.qll diff --git a/python/ql/src/semmle/python/Comment.qll b/python/ql/lib/semmle/python/Comment.qll similarity index 100% rename from python/ql/src/semmle/python/Comment.qll rename to python/ql/lib/semmle/python/Comment.qll diff --git a/python/ql/src/semmle/python/Comparisons.qll b/python/ql/lib/semmle/python/Comparisons.qll similarity index 100% rename from python/ql/src/semmle/python/Comparisons.qll rename to python/ql/lib/semmle/python/Comparisons.qll diff --git a/python/ql/src/semmle/python/Comprehensions.qll b/python/ql/lib/semmle/python/Comprehensions.qll similarity index 100% rename from python/ql/src/semmle/python/Comprehensions.qll rename to python/ql/lib/semmle/python/Comprehensions.qll diff --git a/python/ql/src/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll similarity index 100% rename from python/ql/src/semmle/python/Concepts.qll rename to python/ql/lib/semmle/python/Concepts.qll diff --git a/python/ql/src/semmle/python/Constants.qll b/python/ql/lib/semmle/python/Constants.qll similarity index 100% rename from python/ql/src/semmle/python/Constants.qll rename to python/ql/lib/semmle/python/Constants.qll diff --git a/python/ql/src/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll similarity index 100% rename from python/ql/src/semmle/python/Exprs.qll rename to python/ql/lib/semmle/python/Exprs.qll diff --git a/python/ql/src/semmle/python/Files.qll b/python/ql/lib/semmle/python/Files.qll similarity index 100% rename from python/ql/src/semmle/python/Files.qll rename to python/ql/lib/semmle/python/Files.qll diff --git a/python/ql/src/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll similarity index 100% rename from python/ql/src/semmle/python/Flow.qll rename to python/ql/lib/semmle/python/Flow.qll diff --git a/python/ql/src/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll similarity index 100% rename from python/ql/src/semmle/python/Frameworks.qll rename to python/ql/lib/semmle/python/Frameworks.qll diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/lib/semmle/python/Function.qll similarity index 100% rename from python/ql/src/semmle/python/Function.qll rename to python/ql/lib/semmle/python/Function.qll diff --git a/python/ql/src/semmle/python/GuardedControlFlow.qll b/python/ql/lib/semmle/python/GuardedControlFlow.qll similarity index 100% rename from python/ql/src/semmle/python/GuardedControlFlow.qll rename to python/ql/lib/semmle/python/GuardedControlFlow.qll diff --git a/python/ql/src/semmle/python/Import.qll b/python/ql/lib/semmle/python/Import.qll similarity index 100% rename from python/ql/src/semmle/python/Import.qll rename to python/ql/lib/semmle/python/Import.qll diff --git a/python/ql/src/semmle/python/Keywords.qll b/python/ql/lib/semmle/python/Keywords.qll similarity index 100% rename from python/ql/src/semmle/python/Keywords.qll rename to python/ql/lib/semmle/python/Keywords.qll diff --git a/python/ql/src/semmle/python/Metrics.qll b/python/ql/lib/semmle/python/Metrics.qll similarity index 100% rename from python/ql/src/semmle/python/Metrics.qll rename to python/ql/lib/semmle/python/Metrics.qll diff --git a/python/ql/src/semmle/python/Module.qll b/python/ql/lib/semmle/python/Module.qll similarity index 100% rename from python/ql/src/semmle/python/Module.qll rename to python/ql/lib/semmle/python/Module.qll diff --git a/python/ql/src/semmle/python/Operations.qll b/python/ql/lib/semmle/python/Operations.qll similarity index 100% rename from python/ql/src/semmle/python/Operations.qll rename to python/ql/lib/semmle/python/Operations.qll diff --git a/python/ql/src/semmle/python/PrintAst.qll b/python/ql/lib/semmle/python/PrintAst.qll similarity index 100% rename from python/ql/src/semmle/python/PrintAst.qll rename to python/ql/lib/semmle/python/PrintAst.qll diff --git a/python/ql/src/semmle/python/RegexTreeView.qll b/python/ql/lib/semmle/python/RegexTreeView.qll similarity index 100% rename from python/ql/src/semmle/python/RegexTreeView.qll rename to python/ql/lib/semmle/python/RegexTreeView.qll diff --git a/python/ql/src/semmle/python/SSA.qll b/python/ql/lib/semmle/python/SSA.qll similarity index 100% rename from python/ql/src/semmle/python/SSA.qll rename to python/ql/lib/semmle/python/SSA.qll diff --git a/python/ql/src/semmle/python/Scope.qll b/python/ql/lib/semmle/python/Scope.qll similarity index 100% rename from python/ql/src/semmle/python/Scope.qll rename to python/ql/lib/semmle/python/Scope.qll diff --git a/python/ql/src/semmle/python/SelfAttribute.qll b/python/ql/lib/semmle/python/SelfAttribute.qll similarity index 100% rename from python/ql/src/semmle/python/SelfAttribute.qll rename to python/ql/lib/semmle/python/SelfAttribute.qll diff --git a/python/ql/src/semmle/python/SpecialMethods.qll b/python/ql/lib/semmle/python/SpecialMethods.qll similarity index 100% rename from python/ql/src/semmle/python/SpecialMethods.qll rename to python/ql/lib/semmle/python/SpecialMethods.qll diff --git a/python/ql/src/semmle/python/Stmts.qll b/python/ql/lib/semmle/python/Stmts.qll similarity index 100% rename from python/ql/src/semmle/python/Stmts.qll rename to python/ql/lib/semmle/python/Stmts.qll diff --git a/python/ql/src/semmle/python/TestUtils.qll b/python/ql/lib/semmle/python/TestUtils.qll similarity index 100% rename from python/ql/src/semmle/python/TestUtils.qll rename to python/ql/lib/semmle/python/TestUtils.qll diff --git a/python/ql/src/semmle/python/Unit.qll b/python/ql/lib/semmle/python/Unit.qll similarity index 100% rename from python/ql/src/semmle/python/Unit.qll rename to python/ql/lib/semmle/python/Unit.qll diff --git a/python/ql/src/semmle/python/Variables.qll b/python/ql/lib/semmle/python/Variables.qll similarity index 100% rename from python/ql/src/semmle/python/Variables.qll rename to python/ql/lib/semmle/python/Variables.qll diff --git a/python/ql/src/semmle/python/concepts/CryptoAlgorithms.qll b/python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll similarity index 100% rename from python/ql/src/semmle/python/concepts/CryptoAlgorithms.qll rename to python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll diff --git a/python/ql/src/semmle/python/dataflow/Configuration.qll b/python/ql/lib/semmle/python/dataflow/Configuration.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/Configuration.qll rename to python/ql/lib/semmle/python/dataflow/Configuration.qll diff --git a/python/ql/src/semmle/python/dataflow/DataFlow.qll b/python/ql/lib/semmle/python/dataflow/DataFlow.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/DataFlow.qll rename to python/ql/lib/semmle/python/dataflow/DataFlow.qll diff --git a/python/ql/src/semmle/python/dataflow/Files.qll b/python/ql/lib/semmle/python/dataflow/Files.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/Files.qll rename to python/ql/lib/semmle/python/dataflow/Files.qll diff --git a/python/ql/src/semmle/python/dataflow/Implementation.qll b/python/ql/lib/semmle/python/dataflow/Implementation.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/Implementation.qll rename to python/ql/lib/semmle/python/dataflow/Implementation.qll diff --git a/python/ql/src/semmle/python/dataflow/Legacy.qll b/python/ql/lib/semmle/python/dataflow/Legacy.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/Legacy.qll rename to python/ql/lib/semmle/python/dataflow/Legacy.qll diff --git a/python/ql/src/semmle/python/dataflow/StateTracking.qll b/python/ql/lib/semmle/python/dataflow/StateTracking.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/StateTracking.qll rename to python/ql/lib/semmle/python/dataflow/StateTracking.qll diff --git a/python/ql/src/semmle/python/dataflow/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/TaintTracking.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/TaintTracking.qll rename to python/ql/lib/semmle/python/dataflow/TaintTracking.qll diff --git a/python/ql/src/semmle/python/dataflow/new/BarrierGuards.qll b/python/ql/lib/semmle/python/dataflow/new/BarrierGuards.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/BarrierGuards.qll rename to python/ql/lib/semmle/python/dataflow/new/BarrierGuards.qll diff --git a/python/ql/src/semmle/python/dataflow/new/DataFlow.qll b/python/ql/lib/semmle/python/dataflow/new/DataFlow.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/DataFlow.qll rename to python/ql/lib/semmle/python/dataflow/new/DataFlow.qll diff --git a/python/ql/src/semmle/python/dataflow/new/DataFlow2.qll b/python/ql/lib/semmle/python/dataflow/new/DataFlow2.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/DataFlow2.qll rename to python/ql/lib/semmle/python/dataflow/new/DataFlow2.qll diff --git a/python/ql/src/semmle/python/dataflow/new/DataFlow3.qll b/python/ql/lib/semmle/python/dataflow/new/DataFlow3.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/DataFlow3.qll rename to python/ql/lib/semmle/python/dataflow/new/DataFlow3.qll diff --git a/python/ql/src/semmle/python/dataflow/new/DataFlow4.qll b/python/ql/lib/semmle/python/dataflow/new/DataFlow4.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/DataFlow4.qll rename to python/ql/lib/semmle/python/dataflow/new/DataFlow4.qll diff --git a/python/ql/src/semmle/python/dataflow/new/RemoteFlowSources.qll b/python/ql/lib/semmle/python/dataflow/new/RemoteFlowSources.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/RemoteFlowSources.qll rename to python/ql/lib/semmle/python/dataflow/new/RemoteFlowSources.qll diff --git a/python/ql/src/semmle/python/dataflow/new/SensitiveDataSources.qll b/python/ql/lib/semmle/python/dataflow/new/SensitiveDataSources.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/SensitiveDataSources.qll rename to python/ql/lib/semmle/python/dataflow/new/SensitiveDataSources.qll diff --git a/python/ql/src/semmle/python/dataflow/new/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/TaintTracking.qll rename to python/ql/lib/semmle/python/dataflow/new/TaintTracking.qll diff --git a/python/ql/src/semmle/python/dataflow/new/TaintTracking2.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking2.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/TaintTracking2.qll rename to python/ql/lib/semmle/python/dataflow/new/TaintTracking2.qll diff --git a/python/ql/src/semmle/python/dataflow/new/TaintTracking3.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking3.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/TaintTracking3.qll rename to python/ql/lib/semmle/python/dataflow/new/TaintTracking3.qll diff --git a/python/ql/src/semmle/python/dataflow/new/TaintTracking4.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking4.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/TaintTracking4.qll rename to python/ql/lib/semmle/python/dataflow/new/TaintTracking4.qll diff --git a/python/ql/src/semmle/python/dataflow/new/TypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/TypeTracker.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/TypeTracker.qll rename to python/ql/lib/semmle/python/dataflow/new/TypeTracker.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll b/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/Attributes.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowPublic.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowUtil.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/DataFlowUtil.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/DataFlowUtil.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/LocalSources.qll b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/LocalSources.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPublic.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/TypeTracker.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/readme.md b/python/ql/lib/semmle/python/dataflow/new/internal/readme.md similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/readme.md rename to python/ql/lib/semmle/python/dataflow/new/internal/readme.md diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingParameter.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingParameter.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingParameter.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingParameter.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingParameter.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingParameter.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingParameter.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingParameter.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingParameter.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingParameter.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingParameter.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingParameter.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll diff --git a/python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingParameter.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingParameter.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingParameter.qll rename to python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingParameter.qll diff --git a/python/ql/src/semmle/python/dataflow/old/Configuration.qll b/python/ql/lib/semmle/python/dataflow/old/Configuration.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/Configuration.qll rename to python/ql/lib/semmle/python/dataflow/old/Configuration.qll diff --git a/python/ql/src/semmle/python/dataflow/old/DataFlow.qll b/python/ql/lib/semmle/python/dataflow/old/DataFlow.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/DataFlow.qll rename to python/ql/lib/semmle/python/dataflow/old/DataFlow.qll diff --git a/python/ql/src/semmle/python/dataflow/old/Files.qll b/python/ql/lib/semmle/python/dataflow/old/Files.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/Files.qll rename to python/ql/lib/semmle/python/dataflow/old/Files.qll diff --git a/python/ql/src/semmle/python/dataflow/old/Implementation.qll b/python/ql/lib/semmle/python/dataflow/old/Implementation.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/Implementation.qll rename to python/ql/lib/semmle/python/dataflow/old/Implementation.qll diff --git a/python/ql/src/semmle/python/dataflow/old/Legacy.qll b/python/ql/lib/semmle/python/dataflow/old/Legacy.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/Legacy.qll rename to python/ql/lib/semmle/python/dataflow/old/Legacy.qll diff --git a/python/ql/src/semmle/python/dataflow/old/StateTracking.qll b/python/ql/lib/semmle/python/dataflow/old/StateTracking.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/StateTracking.qll rename to python/ql/lib/semmle/python/dataflow/old/StateTracking.qll diff --git a/python/ql/src/semmle/python/dataflow/old/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll similarity index 100% rename from python/ql/src/semmle/python/dataflow/old/TaintTracking.qll rename to python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll diff --git a/python/ql/src/semmle/python/dependencies/Dependencies.qll b/python/ql/lib/semmle/python/dependencies/Dependencies.qll similarity index 100% rename from python/ql/src/semmle/python/dependencies/Dependencies.qll rename to python/ql/lib/semmle/python/dependencies/Dependencies.qll diff --git a/python/ql/src/semmle/python/dependencies/DependencyKind.qll b/python/ql/lib/semmle/python/dependencies/DependencyKind.qll similarity index 100% rename from python/ql/src/semmle/python/dependencies/DependencyKind.qll rename to python/ql/lib/semmle/python/dependencies/DependencyKind.qll diff --git a/python/ql/src/semmle/python/dependencies/TechInventory.qll b/python/ql/lib/semmle/python/dependencies/TechInventory.qll similarity index 100% rename from python/ql/src/semmle/python/dependencies/TechInventory.qll rename to python/ql/lib/semmle/python/dependencies/TechInventory.qll diff --git a/python/ql/src/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll similarity index 100% rename from python/ql/src/semmle/python/essa/Definitions.qll rename to python/ql/lib/semmle/python/essa/Definitions.qll diff --git a/python/ql/src/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll similarity index 100% rename from python/ql/src/semmle/python/essa/Essa.qll rename to python/ql/lib/semmle/python/essa/Essa.qll diff --git a/python/ql/src/semmle/python/essa/SsaCompute.qll b/python/ql/lib/semmle/python/essa/SsaCompute.qll similarity index 100% rename from python/ql/src/semmle/python/essa/SsaCompute.qll rename to python/ql/lib/semmle/python/essa/SsaCompute.qll diff --git a/python/ql/src/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll similarity index 100% rename from python/ql/src/semmle/python/essa/SsaDefinitions.qll rename to python/ql/lib/semmle/python/essa/SsaDefinitions.qll diff --git a/python/ql/src/semmle/python/filters/GeneratedCode.qll b/python/ql/lib/semmle/python/filters/GeneratedCode.qll similarity index 100% rename from python/ql/src/semmle/python/filters/GeneratedCode.qll rename to python/ql/lib/semmle/python/filters/GeneratedCode.qll diff --git a/python/ql/src/semmle/python/filters/Tests.qll b/python/ql/lib/semmle/python/filters/Tests.qll similarity index 100% rename from python/ql/src/semmle/python/filters/Tests.qll rename to python/ql/lib/semmle/python/filters/Tests.qll diff --git a/python/ql/src/semmle/python/frameworks/Aioch.qll b/python/ql/lib/semmle/python/frameworks/Aioch.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Aioch.qll rename to python/ql/lib/semmle/python/frameworks/Aioch.qll diff --git a/python/ql/src/semmle/python/frameworks/Aiohttp.qll b/python/ql/lib/semmle/python/frameworks/Aiohttp.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Aiohttp.qll rename to python/ql/lib/semmle/python/frameworks/Aiohttp.qll diff --git a/python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll b/python/ql/lib/semmle/python/frameworks/ClickhouseDriver.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/ClickhouseDriver.qll rename to python/ql/lib/semmle/python/frameworks/ClickhouseDriver.qll diff --git a/python/ql/src/semmle/python/frameworks/Cryptodome.qll b/python/ql/lib/semmle/python/frameworks/Cryptodome.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Cryptodome.qll rename to python/ql/lib/semmle/python/frameworks/Cryptodome.qll diff --git a/python/ql/src/semmle/python/frameworks/Cryptography.qll b/python/ql/lib/semmle/python/frameworks/Cryptography.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Cryptography.qll rename to python/ql/lib/semmle/python/frameworks/Cryptography.qll diff --git a/python/ql/src/semmle/python/frameworks/Dill.qll b/python/ql/lib/semmle/python/frameworks/Dill.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Dill.qll rename to python/ql/lib/semmle/python/frameworks/Dill.qll diff --git a/python/ql/src/semmle/python/frameworks/Django.qll b/python/ql/lib/semmle/python/frameworks/Django.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Django.qll rename to python/ql/lib/semmle/python/frameworks/Django.qll diff --git a/python/ql/src/semmle/python/frameworks/Fabric.qll b/python/ql/lib/semmle/python/frameworks/Fabric.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Fabric.qll rename to python/ql/lib/semmle/python/frameworks/Fabric.qll diff --git a/python/ql/src/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Flask.qll rename to python/ql/lib/semmle/python/frameworks/Flask.qll diff --git a/python/ql/src/semmle/python/frameworks/Idna.qll b/python/ql/lib/semmle/python/frameworks/Idna.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Idna.qll rename to python/ql/lib/semmle/python/frameworks/Idna.qll diff --git a/python/ql/src/semmle/python/frameworks/Invoke.qll b/python/ql/lib/semmle/python/frameworks/Invoke.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Invoke.qll rename to python/ql/lib/semmle/python/frameworks/Invoke.qll diff --git a/python/ql/src/semmle/python/frameworks/Jmespath.qll b/python/ql/lib/semmle/python/frameworks/Jmespath.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Jmespath.qll rename to python/ql/lib/semmle/python/frameworks/Jmespath.qll diff --git a/python/ql/src/semmle/python/frameworks/MarkupSafe.qll b/python/ql/lib/semmle/python/frameworks/MarkupSafe.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/MarkupSafe.qll rename to python/ql/lib/semmle/python/frameworks/MarkupSafe.qll diff --git a/python/ql/src/semmle/python/frameworks/Multidict.qll b/python/ql/lib/semmle/python/frameworks/Multidict.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Multidict.qll rename to python/ql/lib/semmle/python/frameworks/Multidict.qll diff --git a/python/ql/src/semmle/python/frameworks/MySQLdb.qll b/python/ql/lib/semmle/python/frameworks/MySQLdb.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/MySQLdb.qll rename to python/ql/lib/semmle/python/frameworks/MySQLdb.qll diff --git a/python/ql/src/semmle/python/frameworks/Mysql.qll b/python/ql/lib/semmle/python/frameworks/Mysql.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Mysql.qll rename to python/ql/lib/semmle/python/frameworks/Mysql.qll diff --git a/python/ql/src/semmle/python/frameworks/PEP249.qll b/python/ql/lib/semmle/python/frameworks/PEP249.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/PEP249.qll rename to python/ql/lib/semmle/python/frameworks/PEP249.qll diff --git a/python/ql/src/semmle/python/frameworks/Peewee.qll b/python/ql/lib/semmle/python/frameworks/Peewee.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Peewee.qll rename to python/ql/lib/semmle/python/frameworks/Peewee.qll diff --git a/python/ql/src/semmle/python/frameworks/Psycopg2.qll b/python/ql/lib/semmle/python/frameworks/Psycopg2.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Psycopg2.qll rename to python/ql/lib/semmle/python/frameworks/Psycopg2.qll diff --git a/python/ql/src/semmle/python/frameworks/PyMySQL.qll b/python/ql/lib/semmle/python/frameworks/PyMySQL.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/PyMySQL.qll rename to python/ql/lib/semmle/python/frameworks/PyMySQL.qll diff --git a/python/ql/src/semmle/python/frameworks/Rsa.qll b/python/ql/lib/semmle/python/frameworks/Rsa.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Rsa.qll rename to python/ql/lib/semmle/python/frameworks/Rsa.qll diff --git a/python/ql/src/semmle/python/frameworks/Simplejson.qll b/python/ql/lib/semmle/python/frameworks/Simplejson.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Simplejson.qll rename to python/ql/lib/semmle/python/frameworks/Simplejson.qll diff --git a/python/ql/src/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Stdlib.qll rename to python/ql/lib/semmle/python/frameworks/Stdlib.qll diff --git a/python/ql/src/semmle/python/frameworks/Tornado.qll b/python/ql/lib/semmle/python/frameworks/Tornado.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Tornado.qll rename to python/ql/lib/semmle/python/frameworks/Tornado.qll diff --git a/python/ql/src/semmle/python/frameworks/Twisted.qll b/python/ql/lib/semmle/python/frameworks/Twisted.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Twisted.qll rename to python/ql/lib/semmle/python/frameworks/Twisted.qll diff --git a/python/ql/src/semmle/python/frameworks/Ujson.qll b/python/ql/lib/semmle/python/frameworks/Ujson.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Ujson.qll rename to python/ql/lib/semmle/python/frameworks/Ujson.qll diff --git a/python/ql/src/semmle/python/frameworks/Werkzeug.qll b/python/ql/lib/semmle/python/frameworks/Werkzeug.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Werkzeug.qll rename to python/ql/lib/semmle/python/frameworks/Werkzeug.qll diff --git a/python/ql/src/semmle/python/frameworks/Yaml.qll b/python/ql/lib/semmle/python/frameworks/Yaml.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Yaml.qll rename to python/ql/lib/semmle/python/frameworks/Yaml.qll diff --git a/python/ql/src/semmle/python/frameworks/Yarl.qll b/python/ql/lib/semmle/python/frameworks/Yarl.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/Yarl.qll rename to python/ql/lib/semmle/python/frameworks/Yarl.qll diff --git a/python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/internal/PEP249Impl.qll rename to python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll diff --git a/python/ql/src/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll b/python/ql/lib/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll rename to python/ql/lib/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll diff --git a/python/ql/src/semmle/python/frameworks/internal/SelfRefMixin.qll b/python/ql/lib/semmle/python/frameworks/internal/SelfRefMixin.qll similarity index 100% rename from python/ql/src/semmle/python/frameworks/internal/SelfRefMixin.qll rename to python/ql/lib/semmle/python/frameworks/internal/SelfRefMixin.qll diff --git a/python/ql/src/semmle/python/libraries/Zope.qll b/python/ql/lib/semmle/python/libraries/Zope.qll similarity index 100% rename from python/ql/src/semmle/python/libraries/Zope.qll rename to python/ql/lib/semmle/python/libraries/Zope.qll diff --git a/python/ql/src/semmle/python/objects/Callables.qll b/python/ql/lib/semmle/python/objects/Callables.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Callables.qll rename to python/ql/lib/semmle/python/objects/Callables.qll diff --git a/python/ql/src/semmle/python/objects/Classes.qll b/python/ql/lib/semmle/python/objects/Classes.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Classes.qll rename to python/ql/lib/semmle/python/objects/Classes.qll diff --git a/python/ql/src/semmle/python/objects/Constants.qll b/python/ql/lib/semmle/python/objects/Constants.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Constants.qll rename to python/ql/lib/semmle/python/objects/Constants.qll diff --git a/python/ql/src/semmle/python/objects/Descriptors.qll b/python/ql/lib/semmle/python/objects/Descriptors.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Descriptors.qll rename to python/ql/lib/semmle/python/objects/Descriptors.qll diff --git a/python/ql/src/semmle/python/objects/Instances.qll b/python/ql/lib/semmle/python/objects/Instances.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Instances.qll rename to python/ql/lib/semmle/python/objects/Instances.qll diff --git a/python/ql/src/semmle/python/objects/Modules.qll b/python/ql/lib/semmle/python/objects/Modules.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Modules.qll rename to python/ql/lib/semmle/python/objects/Modules.qll diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/lib/semmle/python/objects/ObjectAPI.qll similarity index 100% rename from python/ql/src/semmle/python/objects/ObjectAPI.qll rename to python/ql/lib/semmle/python/objects/ObjectAPI.qll diff --git a/python/ql/src/semmle/python/objects/ObjectInternal.qll b/python/ql/lib/semmle/python/objects/ObjectInternal.qll similarity index 100% rename from python/ql/src/semmle/python/objects/ObjectInternal.qll rename to python/ql/lib/semmle/python/objects/ObjectInternal.qll diff --git a/python/ql/src/semmle/python/objects/ObjectModel.md b/python/ql/lib/semmle/python/objects/ObjectModel.md similarity index 100% rename from python/ql/src/semmle/python/objects/ObjectModel.md rename to python/ql/lib/semmle/python/objects/ObjectModel.md diff --git a/python/ql/src/semmle/python/objects/Sequences.qll b/python/ql/lib/semmle/python/objects/Sequences.qll similarity index 100% rename from python/ql/src/semmle/python/objects/Sequences.qll rename to python/ql/lib/semmle/python/objects/Sequences.qll diff --git a/python/ql/src/semmle/python/objects/TObject.qll b/python/ql/lib/semmle/python/objects/TObject.qll similarity index 100% rename from python/ql/src/semmle/python/objects/TObject.qll rename to python/ql/lib/semmle/python/objects/TObject.qll diff --git a/python/ql/src/semmle/python/pointsto/Base.qll b/python/ql/lib/semmle/python/pointsto/Base.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/Base.qll rename to python/ql/lib/semmle/python/pointsto/Base.qll diff --git a/python/ql/src/semmle/python/pointsto/CallGraph.qll b/python/ql/lib/semmle/python/pointsto/CallGraph.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/CallGraph.qll rename to python/ql/lib/semmle/python/pointsto/CallGraph.qll diff --git a/python/ql/src/semmle/python/pointsto/Context.qll b/python/ql/lib/semmle/python/pointsto/Context.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/Context.qll rename to python/ql/lib/semmle/python/pointsto/Context.qll diff --git a/python/ql/src/semmle/python/pointsto/Filters.qll b/python/ql/lib/semmle/python/pointsto/Filters.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/Filters.qll rename to python/ql/lib/semmle/python/pointsto/Filters.qll diff --git a/python/ql/src/semmle/python/pointsto/Final.qll b/python/ql/lib/semmle/python/pointsto/Final.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/Final.qll rename to python/ql/lib/semmle/python/pointsto/Final.qll diff --git a/python/ql/src/semmle/python/pointsto/MRO.qll b/python/ql/lib/semmle/python/pointsto/MRO.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/MRO.qll rename to python/ql/lib/semmle/python/pointsto/MRO.qll diff --git a/python/ql/src/semmle/python/pointsto/Overview.qll b/python/ql/lib/semmle/python/pointsto/Overview.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/Overview.qll rename to python/ql/lib/semmle/python/pointsto/Overview.qll diff --git a/python/ql/src/semmle/python/pointsto/PointsTo.qll b/python/ql/lib/semmle/python/pointsto/PointsTo.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/PointsTo.qll rename to python/ql/lib/semmle/python/pointsto/PointsTo.qll diff --git a/python/ql/src/semmle/python/pointsto/PointsToContext.qll b/python/ql/lib/semmle/python/pointsto/PointsToContext.qll similarity index 100% rename from python/ql/src/semmle/python/pointsto/PointsToContext.qll rename to python/ql/lib/semmle/python/pointsto/PointsToContext.qll diff --git a/python/ql/src/semmle/python/protocols.qll b/python/ql/lib/semmle/python/protocols.qll similarity index 100% rename from python/ql/src/semmle/python/protocols.qll rename to python/ql/lib/semmle/python/protocols.qll diff --git a/python/ql/src/semmle/python/regex.qll b/python/ql/lib/semmle/python/regex.qll similarity index 100% rename from python/ql/src/semmle/python/regex.qll rename to python/ql/lib/semmle/python/regex.qll diff --git a/python/ql/src/semmle/python/security/ClearText.qll b/python/ql/lib/semmle/python/security/ClearText.qll similarity index 100% rename from python/ql/src/semmle/python/security/ClearText.qll rename to python/ql/lib/semmle/python/security/ClearText.qll diff --git a/python/ql/src/semmle/python/security/Crypto.qll b/python/ql/lib/semmle/python/security/Crypto.qll similarity index 100% rename from python/ql/src/semmle/python/security/Crypto.qll rename to python/ql/lib/semmle/python/security/Crypto.qll diff --git a/python/ql/src/semmle/python/security/Exceptions.qll b/python/ql/lib/semmle/python/security/Exceptions.qll similarity index 100% rename from python/ql/src/semmle/python/security/Exceptions.qll rename to python/ql/lib/semmle/python/security/Exceptions.qll diff --git a/python/ql/src/semmle/python/security/Paths.qll b/python/ql/lib/semmle/python/security/Paths.qll similarity index 100% rename from python/ql/src/semmle/python/security/Paths.qll rename to python/ql/lib/semmle/python/security/Paths.qll diff --git a/python/ql/src/semmle/python/security/README.md b/python/ql/lib/semmle/python/security/README.md similarity index 100% rename from python/ql/src/semmle/python/security/README.md rename to python/ql/lib/semmle/python/security/README.md diff --git a/python/ql/src/semmle/python/security/SQL.qll b/python/ql/lib/semmle/python/security/SQL.qll similarity index 100% rename from python/ql/src/semmle/python/security/SQL.qll rename to python/ql/lib/semmle/python/security/SQL.qll diff --git a/python/ql/src/semmle/python/security/SensitiveData.qll b/python/ql/lib/semmle/python/security/SensitiveData.qll similarity index 100% rename from python/ql/src/semmle/python/security/SensitiveData.qll rename to python/ql/lib/semmle/python/security/SensitiveData.qll diff --git a/python/ql/src/semmle/python/security/TaintTracking.qll b/python/ql/lib/semmle/python/security/TaintTracking.qll similarity index 100% rename from python/ql/src/semmle/python/security/TaintTracking.qll rename to python/ql/lib/semmle/python/security/TaintTracking.qll diff --git a/python/ql/src/semmle/python/security/dataflow/ChainedConfigs12.qll b/python/ql/lib/semmle/python/security/dataflow/ChainedConfigs12.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/ChainedConfigs12.qll rename to python/ql/lib/semmle/python/security/dataflow/ChainedConfigs12.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CleartextLogging.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLogging.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CleartextLogging.qll rename to python/ql/lib/semmle/python/security/dataflow/CleartextLogging.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CleartextStorage.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorage.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CleartextStorage.qll rename to python/ql/lib/semmle/python/security/dataflow/CleartextStorage.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CleartextStorageCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CleartextStorageCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CodeInjection.qll b/python/ql/lib/semmle/python/security/dataflow/CodeInjection.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CodeInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/CodeInjection.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CodeInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CodeInjectionCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CodeInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/CodeInjectionCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CommandInjection.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjection.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CommandInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/CommandInjection.qll diff --git a/python/ql/src/semmle/python/security/dataflow/CommandInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/CommandInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/CommandInjectionCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/ExceptionInfo.qll b/python/ql/lib/semmle/python/security/dataflow/ExceptionInfo.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/ExceptionInfo.qll rename to python/ql/lib/semmle/python/security/dataflow/ExceptionInfo.qll diff --git a/python/ql/src/semmle/python/security/dataflow/PathInjection.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjection.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/PathInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/PathInjection.qll diff --git a/python/ql/src/semmle/python/security/dataflow/PathInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/PathInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/PathInjectionCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/PolynomialReDoS.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoS.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/PolynomialReDoS.qll rename to python/ql/lib/semmle/python/security/dataflow/PolynomialReDoS.qll diff --git a/python/ql/src/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/ReflectedXSS.qll b/python/ql/lib/semmle/python/security/dataflow/ReflectedXSS.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/ReflectedXSS.qll rename to python/ql/lib/semmle/python/security/dataflow/ReflectedXSS.qll diff --git a/python/ql/src/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/ReflectedXSSCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/SqlInjection.qll b/python/ql/lib/semmle/python/security/dataflow/SqlInjection.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/SqlInjection.qll rename to python/ql/lib/semmle/python/security/dataflow/SqlInjection.qll diff --git a/python/ql/src/semmle/python/security/dataflow/SqlInjectionCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/SqlInjectionCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/SqlInjectionCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/StackTraceExposure.qll b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposure.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/StackTraceExposure.qll rename to python/ql/lib/semmle/python/security/dataflow/StackTraceExposure.qll diff --git a/python/ql/src/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/StackTraceExposureCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/UnsafeDeserialization.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserialization.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/UnsafeDeserialization.qll rename to python/ql/lib/semmle/python/security/dataflow/UnsafeDeserialization.qll diff --git a/python/ql/src/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/UnsafeDeserializationCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll b/python/ql/lib/semmle/python/security/dataflow/UrlRedirect.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/UrlRedirect.qll rename to python/ql/lib/semmle/python/security/dataflow/UrlRedirect.qll diff --git a/python/ql/src/semmle/python/security/dataflow/UrlRedirectCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/UrlRedirectCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/UrlRedirectCustomizations.qll diff --git a/python/ql/src/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll b/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll rename to python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashing.qll diff --git a/python/ql/src/semmle/python/security/dataflow/WeakSensitiveDataHashingCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingCustomizations.qll similarity index 100% rename from python/ql/src/semmle/python/security/dataflow/WeakSensitiveDataHashingCustomizations.qll rename to python/ql/lib/semmle/python/security/dataflow/WeakSensitiveDataHashingCustomizations.qll diff --git a/python/ql/src/semmle/python/security/flow/AnyCall.qll b/python/ql/lib/semmle/python/security/flow/AnyCall.qll similarity index 100% rename from python/ql/src/semmle/python/security/flow/AnyCall.qll rename to python/ql/lib/semmle/python/security/flow/AnyCall.qll diff --git a/python/ql/src/semmle/python/security/injection/Command.qll b/python/ql/lib/semmle/python/security/injection/Command.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Command.qll rename to python/ql/lib/semmle/python/security/injection/Command.qll diff --git a/python/ql/src/semmle/python/security/injection/Deserialization.qll b/python/ql/lib/semmle/python/security/injection/Deserialization.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Deserialization.qll rename to python/ql/lib/semmle/python/security/injection/Deserialization.qll diff --git a/python/ql/src/semmle/python/security/injection/Exec.qll b/python/ql/lib/semmle/python/security/injection/Exec.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Exec.qll rename to python/ql/lib/semmle/python/security/injection/Exec.qll diff --git a/python/ql/src/semmle/python/security/injection/Marshal.qll b/python/ql/lib/semmle/python/security/injection/Marshal.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Marshal.qll rename to python/ql/lib/semmle/python/security/injection/Marshal.qll diff --git a/python/ql/src/semmle/python/security/injection/Path.qll b/python/ql/lib/semmle/python/security/injection/Path.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Path.qll rename to python/ql/lib/semmle/python/security/injection/Path.qll diff --git a/python/ql/src/semmle/python/security/injection/Pickle.qll b/python/ql/lib/semmle/python/security/injection/Pickle.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Pickle.qll rename to python/ql/lib/semmle/python/security/injection/Pickle.qll diff --git a/python/ql/src/semmle/python/security/injection/Sql.qll b/python/ql/lib/semmle/python/security/injection/Sql.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Sql.qll rename to python/ql/lib/semmle/python/security/injection/Sql.qll diff --git a/python/ql/src/semmle/python/security/injection/Xml.qll b/python/ql/lib/semmle/python/security/injection/Xml.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Xml.qll rename to python/ql/lib/semmle/python/security/injection/Xml.qll diff --git a/python/ql/src/semmle/python/security/injection/Yaml.qll b/python/ql/lib/semmle/python/security/injection/Yaml.qll similarity index 100% rename from python/ql/src/semmle/python/security/injection/Yaml.qll rename to python/ql/lib/semmle/python/security/injection/Yaml.qll diff --git a/python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll b/python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll similarity index 100% rename from python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll rename to python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll diff --git a/python/ql/src/semmle/python/security/performance/ExponentialBackTracking.qll b/python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll similarity index 100% rename from python/ql/src/semmle/python/security/performance/ExponentialBackTracking.qll rename to python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll diff --git a/python/ql/src/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll similarity index 100% rename from python/ql/src/semmle/python/security/performance/ReDoSUtil.qll rename to python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll diff --git a/python/ql/src/semmle/python/security/performance/RegExpTreeView.qll b/python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll similarity index 100% rename from python/ql/src/semmle/python/security/performance/RegExpTreeView.qll rename to python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll diff --git a/python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll b/python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll similarity index 100% rename from python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll rename to python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll diff --git a/python/ql/src/semmle/python/security/strings/Basic.qll b/python/ql/lib/semmle/python/security/strings/Basic.qll similarity index 100% rename from python/ql/src/semmle/python/security/strings/Basic.qll rename to python/ql/lib/semmle/python/security/strings/Basic.qll diff --git a/python/ql/src/semmle/python/security/strings/Common.qll b/python/ql/lib/semmle/python/security/strings/Common.qll similarity index 100% rename from python/ql/src/semmle/python/security/strings/Common.qll rename to python/ql/lib/semmle/python/security/strings/Common.qll diff --git a/python/ql/src/semmle/python/security/strings/External.qll b/python/ql/lib/semmle/python/security/strings/External.qll similarity index 100% rename from python/ql/src/semmle/python/security/strings/External.qll rename to python/ql/lib/semmle/python/security/strings/External.qll diff --git a/python/ql/src/semmle/python/security/strings/Untrusted.qll b/python/ql/lib/semmle/python/security/strings/Untrusted.qll similarity index 100% rename from python/ql/src/semmle/python/security/strings/Untrusted.qll rename to python/ql/lib/semmle/python/security/strings/Untrusted.qll diff --git a/python/ql/src/semmle/python/strings.qll b/python/ql/lib/semmle/python/strings.qll similarity index 100% rename from python/ql/src/semmle/python/strings.qll rename to python/ql/lib/semmle/python/strings.qll diff --git a/python/ql/src/semmle/python/templates/PyxlTags.qll b/python/ql/lib/semmle/python/templates/PyxlTags.qll similarity index 100% rename from python/ql/src/semmle/python/templates/PyxlTags.qll rename to python/ql/lib/semmle/python/templates/PyxlTags.qll diff --git a/python/ql/src/semmle/python/templates/Templates.qll b/python/ql/lib/semmle/python/templates/Templates.qll similarity index 100% rename from python/ql/src/semmle/python/templates/Templates.qll rename to python/ql/lib/semmle/python/templates/Templates.qll diff --git a/python/ql/src/semmle/python/types/Builtins.qll b/python/ql/lib/semmle/python/types/Builtins.qll similarity index 100% rename from python/ql/src/semmle/python/types/Builtins.qll rename to python/ql/lib/semmle/python/types/Builtins.qll diff --git a/python/ql/src/semmle/python/types/ClassObject.qll b/python/ql/lib/semmle/python/types/ClassObject.qll similarity index 100% rename from python/ql/src/semmle/python/types/ClassObject.qll rename to python/ql/lib/semmle/python/types/ClassObject.qll diff --git a/python/ql/src/semmle/python/types/Descriptors.qll b/python/ql/lib/semmle/python/types/Descriptors.qll similarity index 100% rename from python/ql/src/semmle/python/types/Descriptors.qll rename to python/ql/lib/semmle/python/types/Descriptors.qll diff --git a/python/ql/src/semmle/python/types/Exceptions.qll b/python/ql/lib/semmle/python/types/Exceptions.qll similarity index 100% rename from python/ql/src/semmle/python/types/Exceptions.qll rename to python/ql/lib/semmle/python/types/Exceptions.qll diff --git a/python/ql/src/semmle/python/types/Extensions.qll b/python/ql/lib/semmle/python/types/Extensions.qll similarity index 100% rename from python/ql/src/semmle/python/types/Extensions.qll rename to python/ql/lib/semmle/python/types/Extensions.qll diff --git a/python/ql/src/semmle/python/types/FunctionObject.qll b/python/ql/lib/semmle/python/types/FunctionObject.qll similarity index 100% rename from python/ql/src/semmle/python/types/FunctionObject.qll rename to python/ql/lib/semmle/python/types/FunctionObject.qll diff --git a/python/ql/src/semmle/python/types/IgnoredAndApproximations.txt b/python/ql/lib/semmle/python/types/IgnoredAndApproximations.txt similarity index 100% rename from python/ql/src/semmle/python/types/IgnoredAndApproximations.txt rename to python/ql/lib/semmle/python/types/IgnoredAndApproximations.txt diff --git a/python/ql/src/semmle/python/types/ImportTime.qll b/python/ql/lib/semmle/python/types/ImportTime.qll similarity index 100% rename from python/ql/src/semmle/python/types/ImportTime.qll rename to python/ql/lib/semmle/python/types/ImportTime.qll diff --git a/python/ql/src/semmle/python/types/ModuleKind.qll b/python/ql/lib/semmle/python/types/ModuleKind.qll similarity index 100% rename from python/ql/src/semmle/python/types/ModuleKind.qll rename to python/ql/lib/semmle/python/types/ModuleKind.qll diff --git a/python/ql/src/semmle/python/types/ModuleObject.qll b/python/ql/lib/semmle/python/types/ModuleObject.qll similarity index 100% rename from python/ql/src/semmle/python/types/ModuleObject.qll rename to python/ql/lib/semmle/python/types/ModuleObject.qll diff --git a/python/ql/src/semmle/python/types/Object.qll b/python/ql/lib/semmle/python/types/Object.qll similarity index 100% rename from python/ql/src/semmle/python/types/Object.qll rename to python/ql/lib/semmle/python/types/Object.qll diff --git a/python/ql/src/semmle/python/types/Properties.qll b/python/ql/lib/semmle/python/types/Properties.qll similarity index 100% rename from python/ql/src/semmle/python/types/Properties.qll rename to python/ql/lib/semmle/python/types/Properties.qll diff --git a/python/ql/src/semmle/python/types/Version.qll b/python/ql/lib/semmle/python/types/Version.qll similarity index 100% rename from python/ql/src/semmle/python/types/Version.qll rename to python/ql/lib/semmle/python/types/Version.qll diff --git a/python/ql/src/semmle/python/values/StringAttributes.qll b/python/ql/lib/semmle/python/values/StringAttributes.qll similarity index 100% rename from python/ql/src/semmle/python/values/StringAttributes.qll rename to python/ql/lib/semmle/python/values/StringAttributes.qll diff --git a/python/ql/src/semmle/python/web/ClientHttpRequest.qll b/python/ql/lib/semmle/python/web/ClientHttpRequest.qll similarity index 100% rename from python/ql/src/semmle/python/web/ClientHttpRequest.qll rename to python/ql/lib/semmle/python/web/ClientHttpRequest.qll diff --git a/python/ql/src/semmle/python/web/Http.qll b/python/ql/lib/semmle/python/web/Http.qll similarity index 100% rename from python/ql/src/semmle/python/web/Http.qll rename to python/ql/lib/semmle/python/web/Http.qll diff --git a/python/ql/src/semmle/python/web/HttpConstants.qll b/python/ql/lib/semmle/python/web/HttpConstants.qll similarity index 100% rename from python/ql/src/semmle/python/web/HttpConstants.qll rename to python/ql/lib/semmle/python/web/HttpConstants.qll diff --git a/python/ql/src/semmle/python/web/HttpRedirect.qll b/python/ql/lib/semmle/python/web/HttpRedirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/HttpRedirect.qll rename to python/ql/lib/semmle/python/web/HttpRedirect.qll diff --git a/python/ql/src/semmle/python/web/HttpRequest.qll b/python/ql/lib/semmle/python/web/HttpRequest.qll similarity index 100% rename from python/ql/src/semmle/python/web/HttpRequest.qll rename to python/ql/lib/semmle/python/web/HttpRequest.qll diff --git a/python/ql/src/semmle/python/web/HttpResponse.qll b/python/ql/lib/semmle/python/web/HttpResponse.qll similarity index 100% rename from python/ql/src/semmle/python/web/HttpResponse.qll rename to python/ql/lib/semmle/python/web/HttpResponse.qll diff --git a/python/ql/src/semmle/python/web/bottle/General.qll b/python/ql/lib/semmle/python/web/bottle/General.qll similarity index 100% rename from python/ql/src/semmle/python/web/bottle/General.qll rename to python/ql/lib/semmle/python/web/bottle/General.qll diff --git a/python/ql/src/semmle/python/web/bottle/Redirect.qll b/python/ql/lib/semmle/python/web/bottle/Redirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/bottle/Redirect.qll rename to python/ql/lib/semmle/python/web/bottle/Redirect.qll diff --git a/python/ql/src/semmle/python/web/bottle/Request.qll b/python/ql/lib/semmle/python/web/bottle/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/bottle/Request.qll rename to python/ql/lib/semmle/python/web/bottle/Request.qll diff --git a/python/ql/src/semmle/python/web/bottle/Response.qll b/python/ql/lib/semmle/python/web/bottle/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/bottle/Response.qll rename to python/ql/lib/semmle/python/web/bottle/Response.qll diff --git a/python/ql/src/semmle/python/web/cherrypy/General.qll b/python/ql/lib/semmle/python/web/cherrypy/General.qll similarity index 100% rename from python/ql/src/semmle/python/web/cherrypy/General.qll rename to python/ql/lib/semmle/python/web/cherrypy/General.qll diff --git a/python/ql/src/semmle/python/web/cherrypy/Request.qll b/python/ql/lib/semmle/python/web/cherrypy/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/cherrypy/Request.qll rename to python/ql/lib/semmle/python/web/cherrypy/Request.qll diff --git a/python/ql/src/semmle/python/web/cherrypy/Response.qll b/python/ql/lib/semmle/python/web/cherrypy/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/cherrypy/Response.qll rename to python/ql/lib/semmle/python/web/cherrypy/Response.qll diff --git a/python/ql/src/semmle/python/web/client/Requests.qll b/python/ql/lib/semmle/python/web/client/Requests.qll similarity index 100% rename from python/ql/src/semmle/python/web/client/Requests.qll rename to python/ql/lib/semmle/python/web/client/Requests.qll diff --git a/python/ql/src/semmle/python/web/client/StdLib.qll b/python/ql/lib/semmle/python/web/client/StdLib.qll similarity index 100% rename from python/ql/src/semmle/python/web/client/StdLib.qll rename to python/ql/lib/semmle/python/web/client/StdLib.qll diff --git a/python/ql/src/semmle/python/web/django/Db.qll b/python/ql/lib/semmle/python/web/django/Db.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Db.qll rename to python/ql/lib/semmle/python/web/django/Db.qll diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/lib/semmle/python/web/django/General.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/General.qll rename to python/ql/lib/semmle/python/web/django/General.qll diff --git a/python/ql/src/semmle/python/web/django/Model.qll b/python/ql/lib/semmle/python/web/django/Model.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Model.qll rename to python/ql/lib/semmle/python/web/django/Model.qll diff --git a/python/ql/src/semmle/python/web/django/Redirect.qll b/python/ql/lib/semmle/python/web/django/Redirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Redirect.qll rename to python/ql/lib/semmle/python/web/django/Redirect.qll diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/lib/semmle/python/web/django/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Request.qll rename to python/ql/lib/semmle/python/web/django/Request.qll diff --git a/python/ql/src/semmle/python/web/django/Response.qll b/python/ql/lib/semmle/python/web/django/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Response.qll rename to python/ql/lib/semmle/python/web/django/Response.qll diff --git a/python/ql/src/semmle/python/web/django/Sanitizers.qll b/python/ql/lib/semmle/python/web/django/Sanitizers.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Sanitizers.qll rename to python/ql/lib/semmle/python/web/django/Sanitizers.qll diff --git a/python/ql/src/semmle/python/web/django/Shared.qll b/python/ql/lib/semmle/python/web/django/Shared.qll similarity index 100% rename from python/ql/src/semmle/python/web/django/Shared.qll rename to python/ql/lib/semmle/python/web/django/Shared.qll diff --git a/python/ql/src/semmle/python/web/falcon/General.qll b/python/ql/lib/semmle/python/web/falcon/General.qll similarity index 100% rename from python/ql/src/semmle/python/web/falcon/General.qll rename to python/ql/lib/semmle/python/web/falcon/General.qll diff --git a/python/ql/src/semmle/python/web/falcon/Request.qll b/python/ql/lib/semmle/python/web/falcon/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/falcon/Request.qll rename to python/ql/lib/semmle/python/web/falcon/Request.qll diff --git a/python/ql/src/semmle/python/web/falcon/Response.qll b/python/ql/lib/semmle/python/web/falcon/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/falcon/Response.qll rename to python/ql/lib/semmle/python/web/falcon/Response.qll diff --git a/python/ql/src/semmle/python/web/flask/General.qll b/python/ql/lib/semmle/python/web/flask/General.qll similarity index 100% rename from python/ql/src/semmle/python/web/flask/General.qll rename to python/ql/lib/semmle/python/web/flask/General.qll diff --git a/python/ql/src/semmle/python/web/flask/Redirect.qll b/python/ql/lib/semmle/python/web/flask/Redirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/flask/Redirect.qll rename to python/ql/lib/semmle/python/web/flask/Redirect.qll diff --git a/python/ql/src/semmle/python/web/flask/Request.qll b/python/ql/lib/semmle/python/web/flask/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/flask/Request.qll rename to python/ql/lib/semmle/python/web/flask/Request.qll diff --git a/python/ql/src/semmle/python/web/flask/Response.qll b/python/ql/lib/semmle/python/web/flask/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/flask/Response.qll rename to python/ql/lib/semmle/python/web/flask/Response.qll diff --git a/python/ql/src/semmle/python/web/pyramid/Redirect.qll b/python/ql/lib/semmle/python/web/pyramid/Redirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/pyramid/Redirect.qll rename to python/ql/lib/semmle/python/web/pyramid/Redirect.qll diff --git a/python/ql/src/semmle/python/web/pyramid/Request.qll b/python/ql/lib/semmle/python/web/pyramid/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/pyramid/Request.qll rename to python/ql/lib/semmle/python/web/pyramid/Request.qll diff --git a/python/ql/src/semmle/python/web/pyramid/Response.qll b/python/ql/lib/semmle/python/web/pyramid/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/pyramid/Response.qll rename to python/ql/lib/semmle/python/web/pyramid/Response.qll diff --git a/python/ql/src/semmle/python/web/pyramid/View.qll b/python/ql/lib/semmle/python/web/pyramid/View.qll similarity index 100% rename from python/ql/src/semmle/python/web/pyramid/View.qll rename to python/ql/lib/semmle/python/web/pyramid/View.qll diff --git a/python/ql/src/semmle/python/web/stdlib/Request.qll b/python/ql/lib/semmle/python/web/stdlib/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/stdlib/Request.qll rename to python/ql/lib/semmle/python/web/stdlib/Request.qll diff --git a/python/ql/src/semmle/python/web/stdlib/Response.qll b/python/ql/lib/semmle/python/web/stdlib/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/stdlib/Response.qll rename to python/ql/lib/semmle/python/web/stdlib/Response.qll diff --git a/python/ql/src/semmle/python/web/tornado/Redirect.qll b/python/ql/lib/semmle/python/web/tornado/Redirect.qll similarity index 100% rename from python/ql/src/semmle/python/web/tornado/Redirect.qll rename to python/ql/lib/semmle/python/web/tornado/Redirect.qll diff --git a/python/ql/src/semmle/python/web/tornado/Request.qll b/python/ql/lib/semmle/python/web/tornado/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/tornado/Request.qll rename to python/ql/lib/semmle/python/web/tornado/Request.qll diff --git a/python/ql/src/semmle/python/web/tornado/Response.qll b/python/ql/lib/semmle/python/web/tornado/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/tornado/Response.qll rename to python/ql/lib/semmle/python/web/tornado/Response.qll diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/lib/semmle/python/web/tornado/Tornado.qll similarity index 100% rename from python/ql/src/semmle/python/web/tornado/Tornado.qll rename to python/ql/lib/semmle/python/web/tornado/Tornado.qll diff --git a/python/ql/src/semmle/python/web/turbogears/Request.qll b/python/ql/lib/semmle/python/web/turbogears/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/turbogears/Request.qll rename to python/ql/lib/semmle/python/web/turbogears/Request.qll diff --git a/python/ql/src/semmle/python/web/turbogears/Response.qll b/python/ql/lib/semmle/python/web/turbogears/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/turbogears/Response.qll rename to python/ql/lib/semmle/python/web/turbogears/Response.qll diff --git a/python/ql/src/semmle/python/web/turbogears/TurboGears.qll b/python/ql/lib/semmle/python/web/turbogears/TurboGears.qll similarity index 100% rename from python/ql/src/semmle/python/web/turbogears/TurboGears.qll rename to python/ql/lib/semmle/python/web/turbogears/TurboGears.qll diff --git a/python/ql/src/semmle/python/web/twisted/Request.qll b/python/ql/lib/semmle/python/web/twisted/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/twisted/Request.qll rename to python/ql/lib/semmle/python/web/twisted/Request.qll diff --git a/python/ql/src/semmle/python/web/twisted/Response.qll b/python/ql/lib/semmle/python/web/twisted/Response.qll similarity index 100% rename from python/ql/src/semmle/python/web/twisted/Response.qll rename to python/ql/lib/semmle/python/web/twisted/Response.qll diff --git a/python/ql/src/semmle/python/web/twisted/Twisted.qll b/python/ql/lib/semmle/python/web/twisted/Twisted.qll similarity index 100% rename from python/ql/src/semmle/python/web/twisted/Twisted.qll rename to python/ql/lib/semmle/python/web/twisted/Twisted.qll diff --git a/python/ql/src/semmle/python/web/webob/Request.qll b/python/ql/lib/semmle/python/web/webob/Request.qll similarity index 100% rename from python/ql/src/semmle/python/web/webob/Request.qll rename to python/ql/lib/semmle/python/web/webob/Request.qll diff --git a/python/ql/src/semmle/python/xml/XML.qll b/python/ql/lib/semmle/python/xml/XML.qll similarity index 100% rename from python/ql/src/semmle/python/xml/XML.qll rename to python/ql/lib/semmle/python/xml/XML.qll diff --git a/python/ql/src/semmlecode.python.dbscheme b/python/ql/lib/semmlecode.python.dbscheme similarity index 100% rename from python/ql/src/semmlecode.python.dbscheme rename to python/ql/lib/semmlecode.python.dbscheme diff --git a/python/ql/src/semmlecode.python.dbscheme.stats b/python/ql/lib/semmlecode.python.dbscheme.stats similarity index 100% rename from python/ql/src/semmlecode.python.dbscheme.stats rename to python/ql/lib/semmlecode.python.dbscheme.stats diff --git a/python/ql/src/site.qll b/python/ql/lib/site.qll similarity index 100% rename from python/ql/src/site.qll rename to python/ql/lib/site.qll diff --git a/python/ql/src/codeql-suites/python-code-scanning.qls b/python/ql/src/codeql-suites/python-code-scanning.qls index e356f34c26e..1007736770a 100644 --- a/python/ql/src/codeql-suites/python-code-scanning.qls +++ b/python/ql/src/codeql-suites/python-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for Python -- qlpack: codeql-python +- queries: . - apply: code-scanning-selectors.yml from: codeql/suite-helpers diff --git a/python/ql/src/codeql-suites/python-lgtm-full.qls b/python/ql/src/codeql-suites/python-lgtm-full.qls index 42a9b332211..945c5a5ee8d 100644 --- a/python/ql/src/codeql-suites/python-lgtm-full.qls +++ b/python/ql/src/codeql-suites/python-lgtm-full.qls @@ -1,5 +1,5 @@ - description: Standard LGTM queries for Python, including ones not displayed by default -- qlpack: codeql-python +- queries: . - apply: lgtm-selectors.yml from: codeql/suite-helpers # These are only for IDE use. diff --git a/python/ql/src/codeql-suites/python-security-and-quality.qls b/python/ql/src/codeql-suites/python-security-and-quality.qls index 4971989fd5c..2a97a497db0 100644 --- a/python/ql/src/codeql-suites/python-security-and-quality.qls +++ b/python/ql/src/codeql-suites/python-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for Python -- qlpack: codeql-python +- queries: . - apply: security-and-quality-selectors.yml from: codeql/suite-helpers diff --git a/python/ql/src/codeql-suites/python-security-extended.qls b/python/ql/src/codeql-suites/python-security-extended.qls index 068ada84fcd..8b4838c24cc 100644 --- a/python/ql/src/codeql-suites/python-security-extended.qls +++ b/python/ql/src/codeql-suites/python-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for Python -- qlpack: codeql-python +- queries: . - apply: security-extended-selectors.yml from: codeql/suite-helpers diff --git a/python/ql/src/qlpack.lock.yml b/python/ql/src/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/python/ql/src/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 9807b169d44..26f051faa54 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,8 @@ -name: codeql-python -version: 0.0.0 -dbscheme: semmlecode.python.dbscheme +name: codeql/python-queries +version: 0.0.2 +dependencies: + codeql/python-all: ^0.0.2 + codeql/suite-helpers: ^0.0.2 suites: codeql-suites extractor: python +defaultSuiteFile: codeql-suites/python-code-scanning.qls diff --git a/python/ql/test/qlpack.lock.yml b/python/ql/test/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/python/ql/test/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/python/ql/test/qlpack.yml b/python/ql/test/qlpack.yml index aca2524d023..fb108d37022 100644 --- a/python/ql/test/qlpack.yml +++ b/python/ql/test/qlpack.yml @@ -1,5 +1,7 @@ -name: codeql-python-tests +name: codeql/python-tests version: 0.0.0 -libraryPathDependencies: codeql-python +dependencies: + codeql/python-all: ^0.0.1 + codeql/python-queries: ^0.0.1 extractor: python tests: . diff --git a/python/upgrades/qlpack.lock.yml b/python/upgrades/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/python/upgrades/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/python/upgrades/qlpack.yml b/python/upgrades/qlpack.yml index 9939911eb99..baea6039148 100644 --- a/python/upgrades/qlpack.yml +++ b/python/upgrades/qlpack.yml @@ -1,2 +1,4 @@ -name: codeql-python-upgrades +name: codeql/python-upgrades upgrades: . +library: true +version: 0.0.2 From e23df94748fe1ffd28374db96f7a48a05e743982 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 24 Aug 2021 16:12:43 -0700 Subject: [PATCH 338/429] Packaging: Fix identical files script --- config/identical-files.json | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/config/identical-files.json b/config/identical-files.json index ac41c768369..2b8faf0435d 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -21,17 +21,17 @@ "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl2.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImpl4.qll" + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll" ], "DataFlow Java/C++/C#/Python Common": [ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll" + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll" ], "TaintTracking::Configuration Java/C++/C#/Python": [ "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", @@ -46,17 +46,17 @@ "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll", "java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "java/ql/lib/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", - "python/ql/src/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll", - "python/ql/src/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll", - "python/ql/src/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll", - "python/ql/src/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll" + "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll" ], "DataFlow Java/C++/C#/Python Consistency checks": [ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", - "python/ql/src/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll" + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll" ], "DataFlow Java/C# Flow Summaries": [ "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll", @@ -383,7 +383,7 @@ "csharp/ql/lib/semmle/code/csharp/XML.qll", "java/ql/lib/semmle/code/xml/XML.qll", "javascript/ql/src/semmle/javascript/XML.qll", - "python/ql/src/semmle/python/xml/XML.qll" + "python/ql/lib/semmle/python/xml/XML.qll" ], "DuplicationProblems.inc.qhelp": [ "cpp/ql/src/Metrics/Files/DuplicationProblems.inc.qhelp", @@ -444,22 +444,22 @@ ], "CryptoAlgorithms Python/JS": [ "javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll", - "python/ql/src/semmle/python/concepts/CryptoAlgorithms.qll" + "python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll" ], "SensitiveDataHeuristics Python/JS": [ "javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll", - "python/ql/src/semmle/python/security/internal/SensitiveDataHeuristics.qll" + "python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll" ], "ReDoS Util Python/JS": [ "javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll", - "python/ql/src/semmle/python/security/performance/ReDoSUtil.qll" + "python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll" ], "ReDoS Exponential Python/JS": [ "javascript/ql/src/semmle/javascript/security/performance/ExponentialBackTracking.qll", - "python/ql/src/semmle/python/security/performance/ExponentialBackTracking.qll" + "python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll" ], "ReDoS Polynomial Python/JS": [ "javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll", - "python/ql/src/semmle/python/security/performance/SuperlinearBackTracking.qll" + "python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll" ] } From 67a267d97199de05df3b7507f08aca51f28e8f1d Mon Sep 17 00:00:00 2001 From: Anders Peter Fugmann Date: Wed, 25 Aug 2021 08:58:44 +0200 Subject: [PATCH 339/429] Update cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md Co-authored-by: Jonas Jensen --- cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md b/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md index 2903f13d51a..41d00cd8e98 100644 --- a/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md +++ b/cpp/change-notes/2021-08-24-implicit-downcast-from-bitfield.md @@ -1,3 +1,2 @@ lgtm,codescanning -* Extend query `ImplicitDowncastFromBitfield` to detect implicit - downcast on references +* The query `cpp/implicit-bitfield-downcast` now accounts for C++ reference types, which leads to more true positive results. From 605bd19306fa02e909a83473c2f7f06c8b6c518c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 25 Aug 2021 10:19:22 +0200 Subject: [PATCH 340/429] Python: Add CWE-328 to `py/weak-sensitive-data-hashing` Reading over the description at https://cwe.mitre.org/data/definitions/328.html: > The product uses a hashing algorithm that produces a hash value that can be used to determine the original input, or to find an input that can produce the same hash, more efficiently than brute force techniques. For the data that does not require computationally expensive hashing, that will be the exactly problems that this query finds :+1: (that is, MD5, SHA1) --- python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql index 846abd78eaf..e9f7ef7ed71 100644 --- a/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql +++ b/python/ql/src/Security/CWE-327/WeakSensitiveDataHashing.ql @@ -8,6 +8,7 @@ * @id py/weak-sensitive-data-hashing * @tags security * external/cwe/cwe-327 + * external/cwe/cwe-328 * external/cwe/cwe-916 */ From c664d7cfb3d6f28ca0449af3162d207f37f635ef Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 24 Aug 2021 13:27:32 +0200 Subject: [PATCH 341/429] add a `getMaybePromisifiedCall` method in API graphs, and use it to model `child_process` --- .../ql/src/semmle/javascript/ApiGraphs.qll | 34 +++++++++++++++---- .../javascript/frameworks/NodeJSLib.qll | 29 ++++++++-------- .../UnsafeShellCommandConstruction.expected | 9 +++++ .../query-tests/Security/CWE-078/lib/lib.js | 13 ++++++- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/src/semmle/javascript/ApiGraphs.qll index 94ef8cdac70..30fb9980214 100644 --- a/javascript/ql/src/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/src/semmle/javascript/ApiGraphs.qll @@ -57,6 +57,16 @@ module API { */ CallNode getACall() { result = getReturn().getAnImmediateUse() } + /** + * Gets a call to the function represented by this API component, + * or a promisified version of the function. + */ + CallNode getMaybePromisifiedCall() { + result = getACall() + or + result = Impl::getAPromisifiedInvocation(this, _, _) + } + /** * Gets a `new` call to the function represented by this API component. */ @@ -573,10 +583,10 @@ module API { ref = pred.getAnInvocation() or lbl = Label::promised() and - PromiseFlow::loadStep(pred, ref, Promises::valueProp()) + PromiseFlow::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) or lbl = Label::promisedError() and - PromiseFlow::loadStep(pred, ref, Promises::errorProp()) + PromiseFlow::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) ) or exists(DataFlow::Node def, DataFlow::FunctionNode fn | @@ -855,10 +865,9 @@ module API { succ = MkAsyncFuncResult(f) ) or - exists(DataFlow::SourceNode src, int bound, DataFlow::InvokeNode call | - use(pred, src) and + exists(int bound, DataFlow::InvokeNode call | lbl = Label::parameter(bound + call.getNumArgument()) and - succ = MkSyntheticCallbackArg(src, bound, call) + call = getAPromisifiedInvocation(pred, bound, succ) ) } @@ -870,6 +879,18 @@ module API { /** Gets the shortest distance from the root to `nd` in the API graph. */ cached int distanceFromRoot(TApiNode nd) = shortestDistances(MkRoot/0, edge/2)(_, nd, result) + + /** + * Gets a call to a promisified function represented by `callee` where + * `bound` arguments have been bound. + */ + cached + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { + exists(DataFlow::SourceNode src | + Impl::use(callee, src) and + succ = Impl::MkSyntheticCallbackArg(src, bound, result) + ) + } } import Label as EdgeLabel @@ -888,7 +909,8 @@ module API { InvokeNode() { this = callee.getReturn().getAnImmediateUse() or - this = callee.getInstance().getAnImmediateUse() + this = callee.getInstance().getAnImmediateUse() or + this = Impl::getAPromisifiedInvocation(callee, _, _) } /** Gets the API node for the `i`th parameter of this invocation. */ diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index a7ceb09a546..fa753220005 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -398,7 +398,7 @@ module NodeJSLib { override CallExpr astNode; ProcessTermination() { - this = DataFlow::moduleImport("exit").getAnInvocation() + this = API::moduleImport("exit").getAnInvocation() or this = processMember("exit").getACall() } @@ -679,13 +679,14 @@ module NodeJSLib { /** * A call to a method from module `child_process`. */ - private class ChildProcessMethodCall extends SystemCommandExecution, DataFlow::CallNode { + private class ChildProcessMethodCall extends SystemCommandExecution, API::CallNode { string methodName; ChildProcessMethodCall() { - this = maybePromisified(DataFlow::moduleMember("child_process", methodName)).getACall() - or - this = DataFlow::moduleMember("mz/child_process", methodName).getACall() + this = + API::moduleImport(["mz/child_process", "child_process"]) + .getMember(methodName) + .getMaybePromisifiedCall() } private DataFlow::Node getACommandArgument(boolean shell) { @@ -707,7 +708,7 @@ module NodeJSLib { ) ) and // all of the above methods take the command as their first argument - result = getArgument(0) + result = getParameter(0).getARhs() } override DataFlow::Node getACommandArgument() { result = getACommandArgument(_) } @@ -723,7 +724,7 @@ module NodeJSLib { methodName = "spawnSync" ) and // all of the above methods take the argument list as their second argument - result = getArgument(1) + result = getParameter(1).getARhs() } override predicate isSync() { "Sync" = methodName.suffix(methodName.length() - 4) } @@ -731,7 +732,7 @@ module NodeJSLib { override DataFlow::Node getOptionsArg() { not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback not result.getALocalSource() instanceof DataFlow::ArrayCreationNode and // looks like argumentlist - not result = getArgument(0) and + not result = getParameter(0).getARhs() and // fork/spawn and all sync methos always has options as the last argument if methodName.regexpMatch("fork.*") or @@ -740,7 +741,7 @@ module NodeJSLib { then result = getLastArgument() else // the rest (exec/execFile) has the options argument as their second last. - result = getArgument(this.getNumArgument() - 2) + result = getParameter(this.getNumArgument() - 2).getARhs() } } @@ -1027,9 +1028,9 @@ module NodeJSLib { /** * Gets an import of the NodeJS EventEmitter. */ - private DataFlow::SourceNode getAnEventEmitterImport() { - result = DataFlow::moduleImport("events") or - result = DataFlow::moduleMember("events", "EventEmitter") + private API::Node getAnEventEmitterImport() { + result = API::moduleImport("events") or + result = API::moduleImport("events").getMember("EventEmitter") } /** @@ -1051,7 +1052,7 @@ module NodeJSLib { */ private class EventEmitterSubClass extends DataFlow::ClassNode { EventEmitterSubClass() { - this.getASuperClassNode().getALocalSource() = getAnEventEmitterImport() or + this.getASuperClassNode() = getAnEventEmitterImport().getAUse() or this.getADirectSuperClass() instanceof EventEmitterSubClass } } @@ -1186,7 +1187,7 @@ module NodeJSLib { * An instantiation of the `respjs` library, which is an EventEmitter. */ private class RespJS extends NodeJSEventEmitter { - RespJS() { this = DataFlow::moduleImport("respjs").getAnInstantiation() } + RespJS() { this = API::moduleImport("respjs").getAnInstantiation() } } /** 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 421e24aed71..3ff369a3b8d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected @@ -246,6 +246,10 @@ nodes | lib/lib.js:482:40:482:43 | name | | lib/lib.js:483:30:483:33 | name | | lib/lib.js:483:30:483:33 | name | +| lib/lib.js:498:45:498:48 | name | +| lib/lib.js:498:45:498:48 | name | +| lib/lib.js:499:31:499:34 | name | +| lib/lib.js:499:31:499:34 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -558,6 +562,10 @@ edges | lib/lib.js:482:40:482:43 | name | lib/lib.js:483:30:483:33 | name | | lib/lib.js:482:40:482:43 | name | lib/lib.js:483:30:483:33 | name | | lib/lib.js:482:40:482:43 | name | lib/lib.js:483:30:483:33 | name | +| lib/lib.js:498:45:498:48 | name | lib/lib.js:499:31:499:34 | name | +| lib/lib.js:498:45:498:48 | name | lib/lib.js:499:31:499:34 | name | +| lib/lib.js:498:45:498:48 | name | lib/lib.js:499:31:499:34 | name | +| lib/lib.js:498:45:498:48 | name | lib/lib.js:499:31:499:34 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -648,6 +656,7 @@ edges | lib/lib.js:447:13:447:28 | "rm -rf " + name | lib/lib.js:446:20:446:23 | name | lib/lib.js:447:25:447:28 | name | $@ based on $@ is later used in $@. | lib/lib.js:447:13:447:28 | "rm -rf " + name | String concatenation | lib/lib.js:446:20:446:23 | name | library input | lib/lib.js:447:3:447:29 | asyncEx ... + name) | shell command | | lib/lib.js:478:27:478:46 | config.installedPath | lib/lib.js:477:33:477:38 | config | lib/lib.js:478:27:478:46 | config.installedPath | $@ based on $@ is later used in $@. | lib/lib.js:478:27:478:46 | config.installedPath | Path concatenation | lib/lib.js:477:33:477:38 | config | library input | lib/lib.js:479:12:479:20 | exec(cmd) | shell command | | lib/lib.js:483:13:483:33 | ' my na ... + name | lib/lib.js:482:40:482:43 | name | lib/lib.js:483:30:483:33 | name | $@ based on $@ is later used in $@. | lib/lib.js:483:13:483:33 | ' my na ... + name | String concatenation | lib/lib.js:482:40:482:43 | name | library input | lib/lib.js:485:2:485:20 | cp.exec(cmd + args) | shell command | +| lib/lib.js:499:19:499:34 | "rm -rf " + name | lib/lib.js:498:45:498:48 | name | lib/lib.js:499:31:499:34 | name | $@ based on $@ is later used in $@. | lib/lib.js:499:19:499:34 | "rm -rf " + name | String concatenation | lib/lib.js:498:45:498:48 | name | library input | lib/lib.js:499:3:499:35 | MyThing ... + name) | shell command | | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | $@ based on $@ is later used in $@. | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | String concatenation | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command | | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4: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 6b053d64366..f87f10f83a8 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 @@ -488,4 +488,15 @@ module.exports.splitConcat = function (name) { module.exports.myCommand = function (myCommand) { let cmd = `cd ${cwd} ; ${myCommand}`; // OK - the parameter name suggests that it is purposely a shell command. cp.exec(cmd); -} \ No newline at end of file +} + +(function () { + var MyThing = { + cp: require('child_process') + }; + + module.exports.myIndirectThing = function (name) { + MyThing.cp.exec("rm -rf " + name); // NOT OK + } +}); + \ No newline at end of file From 01f7fdfea5de472ecf211f1e71bd89be0ef2110a Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 24 Aug 2021 13:49:18 +0200 Subject: [PATCH 342/429] C#: Update call-context data-flow tests --- .../call-sensitivity/CallSensitivityFlow.cs | 13 ++++++++-- .../CallSensitivityFlow.expected | 26 ++++++++++++------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.cs b/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.cs index a4ee5b7d6da..9470b4536dc 100644 --- a/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.cs @@ -169,6 +169,10 @@ public class A2 a2.M(o); } + public virtual object MOut() => new object(); + + public static object CallMOut(A2 a2) => a2.MOut(); + public void Callsite(InterfaceB intF) { B b = new B(); @@ -179,6 +183,11 @@ public class A2 CallM(b, new object()); // no flow to `Sink()` CallM(this, new object()); // flow to `Sink()` + + var o = CallMOut(this); + Sink(o); // flow + o = CallMOut(b); + Sink(o); // no flow } public class B : A2 @@ -187,11 +196,12 @@ public class A2 { } + + public override object MOut() => throw null; } public class IntA : InterfaceB { - public void Foo(A2 obj, object o, bool cond) { obj.M(o); @@ -210,7 +220,6 @@ public class A2 } } } - } public interface InterfaceA diff --git a/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.expected b/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.expected index 6afa5f20756..7d87f84d155 100644 --- a/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/call-sensitivity/CallSensitivityFlow.expected @@ -31,9 +31,12 @@ edges | CallSensitivityFlow.cs:162:34:162:34 | o : Object | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | | CallSensitivityFlow.cs:167:44:167:44 | o : Object | CallSensitivityFlow.cs:169:14:169:14 | access to parameter o : Object | | CallSensitivityFlow.cs:169:14:169:14 | access to parameter o : Object | CallSensitivityFlow.cs:162:34:162:34 | o : Object | -| CallSensitivityFlow.cs:178:21:178:32 | object creation of type Object : Object | CallSensitivityFlow.cs:195:40:195:40 | o : Object | -| CallSensitivityFlow.cs:181:21:181:32 | object creation of type Object : Object | CallSensitivityFlow.cs:167:44:167:44 | o : Object | -| CallSensitivityFlow.cs:195:40:195:40 | o : Object | CallSensitivityFlow.cs:198:18:198:18 | access to parameter o | +| CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | CallSensitivityFlow.cs:174:45:174:53 | call to method MOut : Object | +| CallSensitivityFlow.cs:174:45:174:53 | call to method MOut : Object | CallSensitivityFlow.cs:187:17:187:30 | call to method CallMOut : Object | +| CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | CallSensitivityFlow.cs:205:40:205:40 | o : Object | +| CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | CallSensitivityFlow.cs:167:44:167:44 | o : Object | +| CallSensitivityFlow.cs:187:17:187:30 | call to method CallMOut : Object | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | +| CallSensitivityFlow.cs:205:40:205:40 | o : Object | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | nodes | CallSensitivityFlow.cs:19:39:19:39 | o : Object | semmle.label | o : Object | | CallSensitivityFlow.cs:23:18:23:18 | access to parameter o | semmle.label | access to parameter o | @@ -78,10 +81,14 @@ nodes | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | semmle.label | access to parameter o | | CallSensitivityFlow.cs:167:44:167:44 | o : Object | semmle.label | o : Object | | CallSensitivityFlow.cs:169:14:169:14 | access to parameter o : Object | semmle.label | access to parameter o : Object | -| CallSensitivityFlow.cs:178:21:178:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | -| CallSensitivityFlow.cs:181:21:181:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | -| CallSensitivityFlow.cs:195:40:195:40 | o : Object | semmle.label | o : Object | -| CallSensitivityFlow.cs:198:18:198:18 | access to parameter o | semmle.label | access to parameter o | +| CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| CallSensitivityFlow.cs:174:45:174:53 | call to method MOut : Object | semmle.label | call to method MOut : Object | +| CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object | +| CallSensitivityFlow.cs:187:17:187:30 | call to method CallMOut : Object | semmle.label | call to method CallMOut : Object | +| CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | semmle.label | access to local variable o | +| CallSensitivityFlow.cs:205:40:205:40 | o : Object | semmle.label | o : Object | +| CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | semmle.label | access to parameter o | #select | CallSensitivityFlow.cs:78:24:78:35 | object creation of type Object : Object | CallSensitivityFlow.cs:78:24:78:35 | object creation of type Object : Object | CallSensitivityFlow.cs:23:18:23:18 | access to parameter o | $@ | CallSensitivityFlow.cs:23:18:23:18 | access to parameter o | access to parameter o | | CallSensitivityFlow.cs:79:25:79:36 | object creation of type Object : Object | CallSensitivityFlow.cs:79:25:79:36 | object creation of type Object : Object | CallSensitivityFlow.cs:31:18:31:18 | access to parameter o | $@ | CallSensitivityFlow.cs:31:18:31:18 | access to parameter o | access to parameter o | @@ -100,5 +107,6 @@ nodes | CallSensitivityFlow.cs:117:26:117:37 | object creation of type Object : Object | CallSensitivityFlow.cs:117:26:117:37 | object creation of type Object : Object | CallSensitivityFlow.cs:128:22:128:22 | access to parameter o | $@ | CallSensitivityFlow.cs:128:22:128:22 | access to parameter o | access to parameter o | | CallSensitivityFlow.cs:118:27:118:38 | object creation of type Object : Object | CallSensitivityFlow.cs:118:27:118:38 | object creation of type Object : Object | CallSensitivityFlow.cs:136:22:136:22 | access to parameter o | $@ | CallSensitivityFlow.cs:136:22:136:22 | access to parameter o | access to parameter o | | CallSensitivityFlow.cs:119:32:119:43 | object creation of type Object : Object | CallSensitivityFlow.cs:119:32:119:43 | object creation of type Object : Object | CallSensitivityFlow.cs:150:18:150:19 | access to local variable o3 | $@ | CallSensitivityFlow.cs:150:18:150:19 | access to local variable o3 | access to local variable o3 | -| CallSensitivityFlow.cs:178:21:178:32 | object creation of type Object : Object | CallSensitivityFlow.cs:178:21:178:32 | object creation of type Object : Object | CallSensitivityFlow.cs:198:18:198:18 | access to parameter o | $@ | CallSensitivityFlow.cs:198:18:198:18 | access to parameter o | access to parameter o | -| CallSensitivityFlow.cs:181:21:181:32 | object creation of type Object : Object | CallSensitivityFlow.cs:181:21:181:32 | object creation of type Object : Object | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | $@ | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | access to parameter o | +| CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | CallSensitivityFlow.cs:172:37:172:48 | object creation of type Object : Object | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | $@ | CallSensitivityFlow.cs:188:14:188:14 | access to local variable o | access to local variable o | +| CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | CallSensitivityFlow.cs:182:21:182:32 | object creation of type Object : Object | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | $@ | CallSensitivityFlow.cs:208:18:208:18 | access to parameter o | access to parameter o | +| CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | CallSensitivityFlow.cs:185:21:185:32 | object creation of type Object : Object | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | $@ | CallSensitivityFlow.cs:164:14:164:14 | access to parameter o | access to parameter o | From 87843a3794ebc90cf01211f8e65301424cc921f7 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 25 Aug 2021 10:37:37 +0200 Subject: [PATCH 343/429] JS: Autoformatttt --- javascript/ql/src/semmle/javascript/frameworks/Templating.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll index 49b1dc46a86..02baad2b008 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Templating.qll @@ -630,7 +630,7 @@ module Templating { override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) } } - /** + /** * The `include` function, seen as an API node, so we can treat it as a template instantiation * in `EjsIncludeCallInTemplate`. * From d405284d3684a6406cefd71751a95d10b02df4ed Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 9 Aug 2021 14:03:30 +0200 Subject: [PATCH 344/429] C#: Make CFG library shared --- csharp/ql/lib/semmle/code/csharp/Caching.qll | 2 +- .../csharp/controlflow/ControlFlowGraph.qll | 14 +- .../internal/ControlFlowGraphImpl.qll | 244 +---- .../internal/ControlFlowGraphImplShared.qll | 945 ++++++++++++++++++ .../internal/ControlFlowGraphImplSpecific.qll | 69 ++ .../csharp/controlflow/internal/Splitting.qll | 633 +----------- .../controlflow/graph/BasicBlock.expected | 2 +- .../controlflow/graph/Consistency.expected | 2 +- .../controlflow/graph/Consistency.ql | 56 +- .../controlflow/graph/Dominance.expected | 6 +- .../controlflow/graph/NodeGraph.expected | 1 + 11 files changed, 1057 insertions(+), 917 deletions(-) create mode 100644 csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll create mode 100644 csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplSpecific.qll diff --git a/csharp/ql/lib/semmle/code/csharp/Caching.qll b/csharp/ql/lib/semmle/code/csharp/Caching.qll index 92417e34586..6a58edef63f 100644 --- a/csharp/ql/lib/semmle/code/csharp/Caching.qll +++ b/csharp/ql/lib/semmle/code/csharp/Caching.qll @@ -18,7 +18,7 @@ module Stages { cached private predicate forceCachingInSameStageRev() { - exists(SplitImpl si) + exists(Split s) or exists(SuccessorType st) or diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll index 061b7674810..96b73d8978d 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/ControlFlowGraph.qll @@ -183,7 +183,7 @@ module ControlFlow { } /** Gets a successor node of a given type, if any. */ - Node getASuccessorByType(SuccessorType t) { result = getASuccessorByType(this, t) } + Node getASuccessorByType(SuccessorType t) { result = getASuccessor(this, t) } /** Gets an immediate successor, if any. */ Node getASuccessor() { result = getASuccessorByType(_) } @@ -255,9 +255,15 @@ module ControlFlow { override Callable getEnclosingCallable() { result = this.getCallable() } - override Location getLocation() { result = getCallable().getLocation() } + private Assignable getAssignable() { this = TEntryNode(result) } - override string toString() { result = "enter " + getCallable().toString() } + override Location getLocation() { + result in [this.getCallable().getLocation(), this.getAssignable().getLocation()] + } + + override string toString() { + result = "enter " + [this.getCallable().toString(), this.getAssignable().toString()] + } } /** A node for a callable exit point, annotated with the type of exit. */ @@ -314,7 +320,7 @@ module ControlFlow { * different splits for the element. */ class ElementNode extends Node, TElementNode { - private Splitting::Splits splits; + private Splits splits; private ControlFlowElement cfe; ElementNode() { this = TElementNode(cfe, splits) } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 63f6943a29c..8a02fb95dee 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -43,13 +43,22 @@ */ import csharp -private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow private import Completion -private import SuccessorType -private import SuccessorTypes private import Splitting private import semmle.code.csharp.ExprOrStmtParent private import semmle.code.csharp.commons.Compilation +import ControlFlowGraphImplShared + +/** An element that defines a new CFG scope. */ +class CfgScope extends Element, @top_level_exprorstmt_parent { + CfgScope() { + this instanceof Callable + or + // For now, static initializer values have their own scope. Eventually, they + // should be treated like instance initializers. + this.(Assignable).(Modifiable).isStatic() + } +} /** * A compilation. @@ -71,16 +80,11 @@ CompilationExt getCompilation(SourceFile f) { result = TBuildless() } -/** An element that defines a new CFG scope. */ -class CfgScope extends Element, @top_level_exprorstmt_parent { - CfgScope() { not this instanceof Attribute } -} - module ControlFlowTree { class Range_ = @callable or @control_flow_element; class Range extends Element, Range_ { - Range() { this = getAChild*(any(CfgScope scope)) } + Range() { this = getAChild*(any(@top_level_exprorstmt_parent p | not p instanceof Attribute)) } } Element getAChild(Element p) { @@ -93,61 +97,6 @@ module ControlFlowTree { 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. - */ - pragma[nomagic] - abstract predicate first(ControlFlowElement first); - - /** - * Holds if `last` with completion `c` is a potential last element executed - * within this control flow element. - */ - pragma[nomagic] - abstract predicate last(ControlFlowElement last, Completion c); - - /** Holds if abnormal execution of `child` should propagate upwards. */ - abstract predicate propagatesAbnormal(ControlFlowElement child); - - /** - * Holds if `succ` is a control flow successor for `pred`, given that `pred` - * finishes with completion `c`. - */ - pragma[nomagic] - abstract predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c); -} - -/** - * Holds if `first` is the first element executed within control flow - * element `cft`. - */ -predicate first(ControlFlowTree cft, ControlFlowElement first) { cft.first(first) } - -/** - * Holds if `last` with completion `c` is a potential last element executed - * within control flow element `cft`. - */ -predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) { - cft.last(last, c) - or - exists(ControlFlowElement cfe | - cft.propagatesAbnormal(cfe) and - last(cfe, last, c) and - not c instanceof NormalCompletion - ) -} - -/** - * Holds if `succ` is a control flow successor for `pred`, given that `pred` - * finishes with completion `c`. - */ -pragma[nomagic] -predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - any(ControlFlowTree cft).succ(pred, succ, c) -} - /** Holds if `first` is first executed when entering `scope`. */ predicate scopeFirst(CfgScope scope, ControlFlowElement first) { scope = @@ -161,8 +110,7 @@ predicate scopeFirst(CfgScope scope, ControlFlowElement first) { ) or expr_parent_top_level_adjusted(any(Expr e | first(e, first)), _, scope) and - not scope instanceof Callable and - not scope instanceof InitializerSplitting::InitializedInstanceMember + not scope instanceof Callable } /** Holds if `scope` is exited when `last` finishes with completion `c`. */ @@ -204,53 +152,6 @@ private class ConstructorTree extends ControlFlowTree, Constructor { } } -/** - * A control flow element where the children are evaluated following a - * standard left-to-right evaluation. The actual evaluation order is - * determined by the predicate `getChildElement()`. - */ -abstract private class StandardElement extends ControlFlowTree { - /** Gets the `i`th child element, in order of evaluation, starting from 0. */ - abstract ControlFlowElement getChildElement(int i); - - /** Gets the first child element of this element. */ - final ControlFlowElement getFirstChild() { result = this.getChildElement(0) } - - /** Holds if this element has no children. */ - final predicate isLeafElement() { not exists(this.getFirstChild()) } - - /** Gets the last child element of this element. */ - final ControlFlowTree getLastChild() { - exists(int last | - result = this.getChildElement(last) and - not exists(this.getChildElement(last + 1)) - ) - } - - final override predicate propagatesAbnormal(ControlFlowElement child) { - child = this.getChildElement(_) - } - - override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - exists(int i | - last(this.getChildElement(i), pred, c) and - first(this.getChildElement(i + 1), succ) and - c instanceof NormalCompletion - ) - } -} - -abstract private class PreOrderTree extends ControlFlowTree { - final override predicate first(ControlFlowElement first) { first = this } -} - -abstract private class PostOrderTree extends ControlFlowTree { - override predicate last(ControlFlowElement last, Completion c) { - last = this and - c.isValidFor(last) - } -} - abstract private class SwitchTree extends ControlFlowTree, Switch { override predicate propagatesAbnormal(ControlFlowElement child) { child = this.getExpr() } @@ -368,7 +269,7 @@ module Expressions { ) } - private class StandardExpr extends StandardElement, PostOrderTree, Expr { + private class StandardExpr extends StandardPostOrderTree, Expr { StandardExpr() { // The following expressions need special treatment not this instanceof LogicalNotExpr and @@ -396,21 +297,6 @@ module Expressions { } final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) } - - final override predicate first(ControlFlowElement first) { - first(this.getFirstChild(), first) - or - not exists(this.getFirstChild()) and - first = this - } - - final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - StandardElement.super.succ(pred, succ, c) - or - last(this.getLastChild(), pred, c) and - succ = this and - c instanceof NormalCompletion - } } /** @@ -1095,7 +981,7 @@ private class PropertyPatternExprExprTree extends PostOrderTree, PropertyPattern } module Statements { - private class StandardStmt extends StandardElement, PreOrderTree, Stmt { + private class StandardStmt extends StandardPreOrderTree, Stmt { StandardStmt() { // The following statements need special treatment not this instanceof IfStmt and @@ -1140,22 +1026,6 @@ module Statements { result = rank[i + 1](ControlFlowElement cfe, int j | cfe = this.getChildElement0(j) | cfe order by j) } - - final override predicate last(ControlFlowElement last, Completion c) { - last(this.getLastChild(), last, c) - or - this.isLeafElement() and - last = this and - c.isValidFor(this) - } - - final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - StandardElement.super.succ(pred, succ, c) - or - pred = this and - first(this.getFirstChild(), succ) and - c instanceof SimpleCompletion - } } private class IfStmtTree extends PreOrderTree, IfStmt { @@ -1779,88 +1649,6 @@ module Statements { } } -cached -private module Cached { - private import semmle.code.csharp.Caching - - private predicate isAbnormalExitType(SuccessorType t) { - t instanceof ExceptionSuccessor or t instanceof ExitSuccessor - } - - /** - * Internal representation of control flow nodes in the control flow graph. - * The control flow graph is pruned for unreachable nodes. - */ - cached - newtype TNode = - TEntryNode(Callable c) { - Stages::ControlFlowStage::forceCachingInSameStage() and - succEntrySplits(c, _, _, _) - } or - TAnnotatedExitNode(Callable c, boolean normal) { - exists(Reachability::SameSplitsBlock b, SuccessorType t | b.isReachable(_) | - succExitSplits(b.getAnElement(), _, c, t) and - if isAbnormalExitType(t) then normal = false else normal = true - ) - } or - TExitNode(Callable c) { - exists(Reachability::SameSplitsBlock b | b.isReachable(_) | - succExitSplits(b.getAnElement(), _, c, _) - ) - } or - TElementNode(ControlFlowElement cfe, Splits splits) { - exists(Reachability::SameSplitsBlock b | b.isReachable(splits) | cfe = b.getAnElement()) - } - - /** Gets a successor node of a given flow type, if any. */ - cached - Node getASuccessorByType(Node pred, SuccessorType t) { - // Callable entry node -> callable body - exists(ControlFlowElement succElement, Splits succSplits | - result = TElementNode(succElement, succSplits) - | - succEntrySplits(pred.(Nodes::EntryNode).getCallable(), succElement, succSplits, t) - ) - or - exists(ControlFlowElement predElement, Splits predSplits | - pred = TElementNode(predElement, predSplits) - | - // Element node -> callable exit (annotated) - result = - any(Nodes::AnnotatedExitNode exit | - succExitSplits(predElement, predSplits, exit.getCallable(), t) and - if isAbnormalExitType(t) then not exit.isNormal() else exit.isNormal() - ) - or - // Element node -> element node - exists(ControlFlowElement succElement, Splits succSplits, Completion c | - result = TElementNode(succElement, succSplits) - | - succSplits(predElement, predSplits, succElement, succSplits, c) and - t = c.getAMatchingSuccessorType() - ) - ) - or - // Callable exit (annotated) -> callable exit - pred.(Nodes::AnnotatedExitNode).getCallable() = result.(Nodes::ExitNode).getCallable() and - t instanceof SuccessorTypes::NormalSuccessor - } - - /** - * Gets a first control flow element executed within `cfe`. - */ - cached - ControlFlowElement getAControlFlowEntryNode(ControlFlowElement cfe) { first(cfe, result) } - - /** - * Gets a potential last control flow element executed within `cfe`. - */ - cached - ControlFlowElement getAControlFlowExitNode(ControlFlowElement cfe) { last(cfe, result, _) } -} - -import Cached - /** A control flow element that is split into multiple control flow nodes. */ class SplitControlFlowElement extends ControlFlowElement { SplitControlFlowElement() { strictcount(this.getAControlFlowNode()) > 1 } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll new file mode 100644 index 00000000000..050a9384729 --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll @@ -0,0 +1,945 @@ +/** Provides language-independent definitions for AST-to-CFG construction. */ + +private import ControlFlowGraphImplSpecific + +/** An element with associated control flow. */ +abstract class ControlFlowTree extends ControlFlowTreeBase { + /** Holds if `first` is the first element executed within this element. */ + pragma[nomagic] + abstract predicate first(ControlFlowElement first); + + /** + * Holds if `last` with completion `c` is a potential last element executed + * within this element. + */ + pragma[nomagic] + abstract predicate last(ControlFlowElement last, Completion c); + + /** Holds if abnormal execution of `child` should propagate upwards. */ + abstract predicate propagatesAbnormal(ControlFlowElement child); + + /** + * Holds if `succ` is a control flow successor for `pred`, given that `pred` + * finishes with completion `c`. + */ + pragma[nomagic] + abstract predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c); +} + +/** + * Holds if `first` is the first element executed within control flow + * element `cft`. + */ +predicate first(ControlFlowTree cft, ControlFlowElement first) { cft.first(first) } + +/** + * Holds if `last` with completion `c` is a potential last element executed + * within control flow element `cft`. + */ +predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) { + cft.last(last, c) + or + exists(ControlFlowElement cfe | + cft.propagatesAbnormal(cfe) and + last(cfe, last, c) and + not completionIsNormal(c) + ) +} + +/** + * Holds if `succ` is a control flow successor for `pred`, given that `pred` + * finishes with completion `c`. + */ +pragma[nomagic] +predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + any(ControlFlowTree cft).succ(pred, succ, c) +} + +/** An element that is executed in pre-order. */ +abstract class PreOrderTree extends ControlFlowTree { + final override predicate first(ControlFlowElement first) { first = this } +} + +/** An element that is executed in post-order. */ +abstract class PostOrderTree extends ControlFlowTree { + override predicate last(ControlFlowElement last, Completion c) { + last = this and + completionIsValidFor(c, last) + } +} + +/** + * An element where the children are evaluated following a standard left-to-right + * evaluation. The actual evaluation order is determined by the predicate + * `getChildElement()`. + */ +abstract class StandardTree extends ControlFlowTree { + /** Gets the `i`th child element, in order of evaluation. */ + abstract ControlFlowElement getChildElement(int i); + + private ControlFlowElement getChildElementRanked(int i) { + result = + rank[i + 1](ControlFlowElement child, int j | + child = this.getChildElement(j) + | + child order by j + ) + } + + /** Gets the first child node of this element. */ + final ControlFlowElement getFirstChildElement() { result = this.getChildElementRanked(0) } + + /** Gets the last child node of this node. */ + final ControlFlowElement getLastChildElement() { + exists(int last | + result = this.getChildElementRanked(last) and + not exists(this.getChildElementRanked(last + 1)) + ) + } + + /** Holds if this element has no children. */ + predicate isLeafElement() { not exists(this.getFirstChildElement()) } + + override predicate propagatesAbnormal(ControlFlowElement child) { + child = this.getChildElement(_) + } + + pragma[nomagic] + override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + exists(int i | + last(this.getChildElementRanked(i), pred, c) and + completionIsNormal(c) and + first(this.getChildElementRanked(i + 1), succ) + ) + } +} + +/** A standard element that is executed in pre-order. */ +abstract class StandardPreOrderTree extends StandardTree, PreOrderTree { + override predicate last(ControlFlowElement last, Completion c) { + last(this.getLastChildElement(), last, c) + or + this.isLeafElement() and + completionIsValidFor(c, this) and + last = this + } + + override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + StandardTree.super.succ(pred, succ, c) + or + pred = this and + first(this.getFirstChildElement(), succ) and + completionIsSimple(c) + } +} + +/** A standard element that is executed in post-order. */ +abstract class StandardPostOrderTree extends StandardTree, PostOrderTree { + override predicate first(ControlFlowElement first) { + first(this.getFirstChildElement(), first) + or + not exists(this.getFirstChildElement()) and + first = this + } + + override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + StandardTree.super.succ(pred, succ, c) + or + last(this.getLastChildElement(), pred, c) and + succ = this and + completionIsNormal(c) + } +} + +/** An element that is a leaf in the control flow graph. */ +abstract class LeafTree extends PreOrderTree, PostOrderTree { + override predicate propagatesAbnormal(ControlFlowElement child) { none() } + + override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { none() } +} + +/** + * Holds if split kinds `sk1` and `sk2` may overlap. That is, they may apply + * to at least one common AST node inside `scope`. + */ +private predicate overlapping(CfgScope scope, SplitKind sk1, SplitKind sk2) { + exists(ControlFlowElement e | + sk1.appliesTo(e) and + sk2.appliesTo(e) and + scope = getCfgScope(e) + ) +} + +/** + * A split kind. Each control flow node can have at most one split of a + * given kind. + */ +abstract class SplitKind extends SplitKindBase { + /** Gets a split of this kind. */ + SplitImpl getASplit() { result.getKind() = this } + + /** Holds if some split of this kind applies to AST node `n`. */ + predicate appliesTo(ControlFlowElement n) { this.getASplit().appliesTo(n) } + + /** + * Gets a unique integer representing this split kind. The integer is used + * to represent sets of splits as ordered lists. + */ + abstract int getListOrder(); + + /** Gets the rank of this split kind among all overlapping kinds for `c`. */ + private int getRank(CfgScope scope) { + this = rank[result](SplitKind sk | overlapping(scope, this, sk) | sk order by sk.getListOrder()) + } + + /** + * Holds if this split kind is enabled for AST node `n`. For performance reasons, + * the number of splits is restricted by the `maxSplits()` predicate. + */ + predicate isEnabled(ControlFlowElement n) { + this.appliesTo(n) and + this.getRank(getCfgScope(n)) <= maxSplits() + } + + /** + * Gets the rank of this split kind among all the split kinds that apply to + * AST node `n`. The rank is based on the order defined by `getListOrder()`. + */ + int getListRank(ControlFlowElement n) { + this.isEnabled(n) and + this = rank[result](SplitKind sk | sk.appliesTo(n) | sk order by sk.getListOrder()) + } + + /** Gets a textual representation of this split kind. */ + abstract string toString(); +} + +/** Provides the interface for implementing an entity to split on. */ +abstract class SplitImpl extends Split { + /** Gets the kind of this split. */ + abstract SplitKind getKind(); + + /** + * Holds if this split is entered when control passes from `pred` to `succ` with + * completion `c`. + * + * Invariant: `hasEntry(pred, succ, c) implies succ(pred, succ, c)`. + */ + abstract predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c); + + /** + * Holds if this split is entered when control passes from `scope` to the entry point + * `first`. + * + * Invariant: `hasEntryScope(scope, first) implies scopeFirst(scope, first)`. + */ + abstract predicate hasEntryScope(CfgScope scope, ControlFlowElement first); + + /** + * Holds if this split is left when control passes from `pred` to `succ` with + * completion `c`. + * + * Invariant: `hasExit(pred, succ, c) implies succ(pred, succ, c)`. + */ + abstract predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c); + + /** + * Holds if this split is left when control passes from `last` out of the enclosing + * scope `scope` with completion `c`. + * + * Invariant: `hasExitScope(scope, last, c) implies scopeLast(scope, last, c)` + */ + abstract predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c); + + /** + * Holds if this split is maintained when control passes from `pred` to `succ` with + * completion `c`. + * + * Invariant: `hasSuccessor(pred, succ, c) implies succ(pred, succ, c)` + */ + abstract predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c); + + /** Holds if this split applies to control flow element `cfe`. */ + final predicate appliesTo(ControlFlowElement cfe) { + this.hasEntry(_, cfe, _) + or + this.hasEntryScope(_, cfe) + or + exists(ControlFlowElement pred | this.appliesTo(pred) | this.hasSuccessor(pred, cfe, _)) + } + + /** The `succ` relation restricted to predecessors `pred` that this split applies to. */ + pragma[noinline] + final predicate appliesSucc(ControlFlowElement pred, ControlFlowElement succ, Completion c) { + this.appliesTo(pred) and + succ(pred, succ, c) + } +} + +/** + * A set of control flow node splits. The set is represented by a list of splits, + * ordered by ascending rank. + */ +class Splits extends TSplits { + /** Gets a textual representation of this set of splits. */ + string toString() { result = splitsToString(this) } + + /** Gets a split belonging to this set of splits. */ + SplitImpl getASplit() { + exists(SplitImpl head, Splits tail | this = TSplitsCons(head, tail) | + result = head + or + result = tail.getASplit() + ) + } +} + +private predicate succEntrySplitsFromRank( + CfgScope pred, ControlFlowElement succ, Splits splits, int rnk +) { + splits = TSplitsNil() and + scopeFirst(pred, succ) and + rnk = 0 + or + exists(SplitImpl head, Splits tail | succEntrySplitsCons(pred, succ, head, tail, rnk) | + splits = TSplitsCons(head, tail) + ) +} + +private predicate succEntrySplitsCons( + CfgScope pred, ControlFlowElement succ, SplitImpl head, Splits tail, int rnk +) { + succEntrySplitsFromRank(pred, succ, tail, rnk - 1) and + head.hasEntryScope(pred, succ) and + rnk = head.getKind().getListRank(succ) +} + +/** + * Holds if `succ` with splits `succSplits` is the first element that is executed + * when entering callable `pred`. + */ +pragma[noinline] +private predicate succEntrySplits( + CfgScope pred, ControlFlowElement succ, Splits succSplits, SuccessorType t +) { + exists(int rnk | + scopeFirst(pred, succ) and + successorTypeIsSimple(t) and + succEntrySplitsFromRank(pred, succ, succSplits, rnk) + | + rnk = 0 and + not any(SplitImpl split).hasEntryScope(pred, succ) + or + rnk = max(SplitImpl split | split.hasEntryScope(pred, succ) | split.getKind().getListRank(succ)) + ) +} + +/** + * Holds if `pred` with splits `predSplits` can exit the enclosing callable + * `succ` with type `t`. + */ +private predicate succExitSplits( + ControlFlowElement pred, Splits predSplits, CfgScope succ, SuccessorType t +) { + exists(Reachability::SameSplitsBlock b, Completion c | pred = b.getAnElement() | + b.isReachable(predSplits) and + t = getAMatchingSuccessorType(c) and + scopeLast(succ, pred, c) and + forall(SplitImpl predSplit | predSplit = predSplits.getASplit() | + predSplit.hasExitScope(succ, pred, c) + ) + ) +} + +/** + * Provides a predicate for the successor relation with split information, + * as well as logic used to construct the type `TSplits` representing sets + * of splits. Only sets of splits that can be reached are constructed, hence + * the predicates are mutually recursive. + * + * For the successor relation + * + * ```ql + * succSplits(ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, Completion c) + * ``` + * + * the following invariants are maintained: + * + * 1. `pred` is reachable with split set `predSplits`. + * 2. For all `split` in `predSplits`: + * - If `split.hasSuccessor(pred, succ, c)` then `split` in `succSplits`. + * 3. For all `split` in `predSplits`: + * - If `split.hasExit(pred, succ, c)` and not `split.hasEntry(pred, succ, c)` then + * `split` not in `succSplits`. + * 4. For all `split` with kind not in `predSplits`: + * - If `split.hasEntry(pred, succ, c)` then `split` in `succSplits`. + * 5. For all `split` in `succSplits`: + * - `split.hasSuccessor(pred, succ, c)` and `split` in `predSplits`, or + * - `split.hasEntry(pred, succ, c)`. + * + * The algorithm divides into four cases: + * + * 1. The set of splits for the successor is the same as the set of splits + * for the predecessor: + * a) The successor is in the same `SameSplitsBlock` as the predecessor. + * b) The successor is *not* in the same `SameSplitsBlock` as the predecessor. + * 2. The set of splits for the successor is different from the set of splits + * for the predecessor: + * a) The set of splits for the successor is *maybe* non-empty. + * b) The set of splits for the successor is *always* empty. + * + * Only case 2a may introduce new sets of splits, so only predicates from + * this case are used in the definition of `TSplits`. + * + * The predicates in this module are named after the cases above. + */ +private module SuccSplits { + private predicate succInvariant1( + Reachability::SameSplitsBlock b, ControlFlowElement pred, Splits predSplits, + ControlFlowElement succ, Completion c + ) { + pred = b.getAnElement() and + b.isReachable(predSplits) and + succ(pred, succ, c) + } + + private predicate case1b0( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c + ) { + exists(Reachability::SameSplitsBlock b | + // Invariant 1 + succInvariant1(b, pred, predSplits, succ, c) + | + (succ = b.getAnElement() implies succ = b) and + // Invariant 4 + not exists(SplitImpl split | split.hasEntry(pred, succ, c)) + ) + } + + /** + * Case 1b. + * + * Invariants 1 and 4 hold in the base case, and invariants 2, 3, and 5 are + * maintained for all splits in `predSplits` (= `succSplits`), except + * possibly for the splits in `except`. + * + * The predicate is written using explicit recursion, as opposed to a `forall`, + * to avoid negative recursion. + */ + private predicate case1bForall( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, Splits except + ) { + case1b0(pred, predSplits, succ, c) and + except = predSplits + or + exists(SplitImpl split | + case1bForallCons(pred, predSplits, succ, c, split, except) and + split.hasSuccessor(pred, succ, c) + ) + } + + pragma[noinline] + private predicate case1bForallCons( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, + SplitImpl exceptHead, Splits exceptTail + ) { + case1bForall(pred, predSplits, succ, c, TSplitsCons(exceptHead, exceptTail)) + } + + private predicate case1( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c + ) { + // Case 1a + exists(Reachability::SameSplitsBlock b | succInvariant1(b, pred, predSplits, succ, c) | + succ = b.getAnElement() and + not succ = b + ) + or + // Case 1b + case1bForall(pred, predSplits, succ, c, TSplitsNil()) + } + + pragma[noinline] + private SplitImpl succInvariant1GetASplit( + Reachability::SameSplitsBlock b, ControlFlowElement pred, Splits predSplits, + ControlFlowElement succ, Completion c + ) { + succInvariant1(b, pred, predSplits, succ, c) and + result = predSplits.getASplit() + } + + private predicate case2aux( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c + ) { + exists(Reachability::SameSplitsBlock b | + succInvariant1(b, pred, predSplits, succ, c) and + (succ = b.getAnElement() implies succ = b) + | + succInvariant1GetASplit(b, pred, predSplits, succ, c).hasExit(pred, succ, c) + or + any(SplitImpl split).hasEntry(pred, succ, c) + ) + } + + /** + * Holds if `succSplits` should not inherit a split of kind `sk` from + * `predSplits`, except possibly because of a split in `except`. + * + * The predicate is written using explicit recursion, as opposed to a `forall`, + * to avoid negative recursion. + */ + private predicate case2aNoneInheritedOfKindForall( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk, + Splits except + ) { + case2aux(pred, predSplits, succ, c) and + sk.appliesTo(succ) and + except = predSplits + or + exists(Splits mid, SplitImpl split | + case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk, mid) and + mid = TSplitsCons(split, except) + | + split.getKind() = any(SplitKind sk0 | sk0 != sk and sk0.appliesTo(succ)) + or + split.hasExit(pred, succ, c) + ) + } + + pragma[nomagic] + private predicate entryOfKind( + ControlFlowElement pred, ControlFlowElement succ, Completion c, SplitImpl split, SplitKind sk + ) { + split.hasEntry(pred, succ, c) and + sk = split.getKind() + } + + /** Holds if `succSplits` should not have a split of kind `sk`. */ + pragma[nomagic] + private predicate case2aNoneOfKind( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk + ) { + // None inherited from predecessor + case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk, TSplitsNil()) and + // None newly entered into + not entryOfKind(pred, succ, c, _, sk) + } + + /** Holds if `succSplits` should not have a split of kind `sk` at rank `rnk`. */ + pragma[nomagic] + private predicate case2aNoneAtRank( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk + ) { + exists(SplitKind sk | case2aNoneOfKind(pred, predSplits, succ, c, sk) | + rnk = sk.getListRank(succ) + ) + } + + pragma[nomagic] + private SplitImpl case2auxGetAPredecessorSplit( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c + ) { + case2aux(pred, predSplits, succ, c) and + result = predSplits.getASplit() + } + + /** Gets a split that should be in `succSplits`. */ + pragma[nomagic] + private SplitImpl case2aSome( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk + ) { + ( + // Inherited from predecessor + result = case2auxGetAPredecessorSplit(pred, predSplits, succ, c) and + result.hasSuccessor(pred, succ, c) + or + // Newly entered into + exists(SplitKind sk0 | + case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk0, TSplitsNil()) + | + entryOfKind(pred, succ, c, result, sk0) + ) + ) and + sk = result.getKind() + } + + /** Gets a split that should be in `succSplits` at rank `rnk`. */ + pragma[nomagic] + SplitImpl case2aSomeAtRank( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk + ) { + exists(SplitKind sk | result = case2aSome(pred, predSplits, succ, c, sk) | + rnk = sk.getListRank(succ) + ) + } + + /** + * Case 2a. + * + * As opposed to the other cases, in this case we need to construct a new set + * of splits `succSplits`. Since this involves constructing the very IPA type, + * we cannot recurse directly over the structure of `succSplits`. Instead, we + * recurse over the ranks of all splits that *might* be in `succSplits`. + * + * - Invariant 1 holds in the base case, + * - invariant 2 holds for all splits with rank at least `rnk`, + * - invariant 3 holds for all splits in `predSplits`, + * - invariant 4 holds for all splits in `succSplits` with rank at least `rnk`, + * and + * - invariant 4 holds for all splits in `succSplits` with rank at least `rnk`. + */ + predicate case2aFromRank( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + Completion c, int rnk + ) { + case2aux(pred, predSplits, succ, c) and + succSplits = TSplitsNil() and + rnk = max(any(SplitKind sk).getListRank(succ)) + 1 + or + case2aFromRank(pred, predSplits, succ, succSplits, c, rnk + 1) and + case2aNoneAtRank(pred, predSplits, succ, c, rnk) + or + exists(Splits mid, SplitImpl split | split = case2aCons(pred, predSplits, succ, mid, c, rnk) | + succSplits = TSplitsCons(split, mid) + ) + } + + pragma[noinline] + private SplitImpl case2aCons( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + Completion c, int rnk + ) { + case2aFromRank(pred, predSplits, succ, succSplits, c, rnk + 1) and + result = case2aSomeAtRank(pred, predSplits, succ, c, rnk) + } + + /** + * Case 2b. + * + * Invariants 1, 4, and 5 hold in the base case, and invariants 2 and 3 are + * maintained for all splits in `predSplits`, except possibly for the splits + * in `except`. + * + * The predicate is written using explicit recursion, as opposed to a `forall`, + * to avoid negative recursion. + */ + private predicate case2bForall( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, Splits except + ) { + // Invariant 1 + case2aux(pred, predSplits, succ, c) and + // Invariants 4 and 5 + not any(SplitKind sk).appliesTo(succ) and + except = predSplits + or + exists(SplitImpl split | case2bForallCons(pred, predSplits, succ, c, split, except) | + // Invariants 2 and 3 + split.hasExit(pred, succ, c) + ) + } + + pragma[noinline] + private predicate case2bForallCons( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, + SplitImpl exceptHead, Splits exceptTail + ) { + case2bForall(pred, predSplits, succ, c, TSplitsCons(exceptHead, exceptTail)) + } + + private predicate case2( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + Completion c + ) { + case2aFromRank(pred, predSplits, succ, succSplits, c, 1) + or + case2bForall(pred, predSplits, succ, c, TSplitsNil()) and + succSplits = TSplitsNil() + } + + /** + * Holds if `succ` with splits `succSplits` is a successor of type `t` for `pred` + * with splits `predSplits`. + */ + predicate succSplits( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + Completion c + ) { + case1(pred, predSplits, succ, c) and + succSplits = predSplits + or + case2(pred, predSplits, succ, succSplits, c) + } +} + +import SuccSplits + +/** Provides logic for calculating reachable control flow nodes. */ +private module Reachability { + /** + * Holds if `cfe` is a control flow element where the set of possible splits may + * be different from the set of possible splits for one of `cfe`'s predecessors. + * That is, `cfe` starts a new block of elements with the same set of splits. + */ + private predicate startsSplits(ControlFlowElement cfe) { + scopeFirst(_, cfe) + or + exists(SplitImpl s | + s.hasEntry(_, cfe, _) + or + s.hasExit(_, cfe, _) + ) + or + exists(ControlFlowElement pred, SplitImpl split, Completion c | succ(pred, cfe, c) | + split.appliesTo(pred) and + not split.hasSuccessor(pred, cfe, c) + ) + } + + private predicate intraSplitsSucc(ControlFlowElement pred, ControlFlowElement succ) { + succ(pred, succ, _) and + not startsSplits(succ) + } + + private predicate splitsBlockContains(ControlFlowElement start, ControlFlowElement cfe) = + fastTC(intraSplitsSucc/2)(start, cfe) + + /** + * A block of control flow elements where the set of splits is guaranteed + * to remain unchanged, represented by the first element in the block. + */ + class SameSplitsBlock extends ControlFlowElement { + SameSplitsBlock() { startsSplits(this) } + + /** Gets a control flow element in this block. */ + ControlFlowElement getAnElement() { + splitsBlockContains(this, result) + or + result = this + } + + pragma[noinline] + private SameSplitsBlock getASuccessor(Splits predSplits, Splits succSplits) { + exists(ControlFlowElement pred | pred = this.getAnElement() | + succSplits(pred, predSplits, result, succSplits, _) + ) + } + + /** + * Holds if the elements of this block are reachable from a callable entry + * point, with the splits `splits`. + */ + predicate isReachable(Splits splits) { + // Base case + succEntrySplits(_, this, splits, _) + or + // Recursive case + exists(SameSplitsBlock pred, Splits predSplits | pred.isReachable(predSplits) | + this = pred.getASuccessor(predSplits, splits) + ) + } + } +} + +cached +private module Cached { + /** + * If needed, call this predicate from `ControlFlowGraphImplSpecific.qll` in order to + * force a stage-dependency on the `ControlFlowGraphImplShared.qll` stage and therby + * collapsing the two stages. + */ + cached + predicate forceCachingInSameStage() { any() } + + cached + newtype TSplits = + TSplitsNil() or + TSplitsCons(SplitImpl head, Splits tail) { + exists( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk + | + case2aFromRank(pred, predSplits, succ, tail, c, rnk + 1) and + head = case2aSomeAtRank(pred, predSplits, succ, c, rnk) + ) + or + succEntrySplitsCons(_, _, head, tail, _) + } + + cached + string splitsToString(Splits splits) { + splits = TSplitsNil() and + result = "" + or + exists(SplitImpl head, Splits tail, string headString, string tailString | + splits = TSplitsCons(head, tail) + | + headString = head.toString() and + tailString = tail.toString() and + if tailString = "" + then result = headString + else + if headString = "" + then result = tailString + else result = headString + ", " + tailString + ) + } + + /** + * Internal representation of control flow nodes in the control flow graph. + * The control flow graph is pruned for unreachable nodes. + */ + cached + newtype TNode = + TEntryNode(CfgScope scope) { succEntrySplits(scope, _, _, _) } or + TAnnotatedExitNode(CfgScope scope, boolean normal) { + exists(Reachability::SameSplitsBlock b, SuccessorType t | b.isReachable(_) | + succExitSplits(b.getAnElement(), _, scope, t) and + if isAbnormalExitType(t) then normal = false else normal = true + ) + } or + TExitNode(CfgScope scope) { + exists(Reachability::SameSplitsBlock b | b.isReachable(_) | + succExitSplits(b.getAnElement(), _, scope, _) + ) + } or + TElementNode(ControlFlowElement cfe, Splits splits) { + exists(Reachability::SameSplitsBlock b | b.isReachable(splits) | cfe = b.getAnElement()) + } + + /** Gets a successor node of a given flow type, if any. */ + cached + TNode getASuccessor(TNode pred, SuccessorType t) { + // Callable entry node -> callable body + exists(ControlFlowElement succElement, Splits succSplits, CfgScope scope | + result = TElementNode(succElement, succSplits) and + pred = TEntryNode(scope) and + succEntrySplits(scope, succElement, succSplits, t) + ) + or + exists(ControlFlowElement predElement, Splits predSplits | + pred = TElementNode(predElement, predSplits) + | + // Element node -> callable exit (annotated) + exists(CfgScope scope, boolean normal | + result = TAnnotatedExitNode(scope, normal) and + succExitSplits(predElement, predSplits, scope, t) and + if isAbnormalExitType(t) then normal = false else normal = true + ) + or + // Element node -> element node + exists(ControlFlowElement succElement, Splits succSplits, Completion c | + result = TElementNode(succElement, succSplits) + | + succSplits(predElement, predSplits, succElement, succSplits, c) and + t = getAMatchingSuccessorType(c) + ) + ) + or + // Callable exit (annotated) -> callable exit + exists(CfgScope scope | + pred = TAnnotatedExitNode(scope, _) and + result = TExitNode(scope) and + successorTypeIsSimple(t) + ) + } + + /** + * Gets a first control flow element executed within `cfe`. + */ + cached + ControlFlowElement getAControlFlowEntryNode(ControlFlowElement cfe) { first(cfe, result) } + + /** + * Gets a potential last control flow element executed within `cfe`. + */ + cached + ControlFlowElement getAControlFlowExitNode(ControlFlowElement cfe) { last(cfe, result, _) } +} + +import Cached + +/** + * Import this module into a `.ql` file of `@kind graph` to render a CFG. The + * graph is restricted to nodes from `RelevantNode`. + */ +module TestOutput { + abstract class RelevantNode extends Node { } + + query predicate nodes(RelevantNode n, string attr, string val) { + attr = "semmle.order" and + val = + any(int i | + n = + rank[i](RelevantNode p, Location l | + l = p.getLocation() + | + p + order by + l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(), + l.getStartColumn() + ) + ).toString() + } + + query predicate edges(RelevantNode pred, RelevantNode succ, string attr, string val) { + exists(SuccessorType t | succ = getASuccessor(pred, t) | + attr = "semmle.label" and + if successorTypeIsSimple(t) then val = "" else val = t.toString() + ) + } +} + +/** Provides a set of splitting-related consistency queries. */ +module Consistency { + query predicate nonUniqueSetRepresentation(Splits s1, Splits s2) { + forex(Split s | s = s1.getASplit() | s = s2.getASplit()) and + forex(Split s | s = s2.getASplit() | s = s1.getASplit()) and + s1 != s2 + } + + query predicate breakInvariant2( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + SplitImpl split, Completion c + ) { + succSplits(pred, predSplits, succ, succSplits, c) and + split = predSplits.getASplit() and + split.hasSuccessor(pred, succ, c) and + not split = succSplits.getASplit() + } + + query predicate breakInvariant3( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + SplitImpl split, Completion c + ) { + succSplits(pred, predSplits, succ, succSplits, c) and + split = predSplits.getASplit() and + split.hasExit(pred, succ, c) and + not split.hasEntry(pred, succ, c) and + split = succSplits.getASplit() + } + + query predicate breakInvariant4( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + SplitImpl split, Completion c + ) { + succSplits(pred, predSplits, succ, succSplits, c) and + split.hasEntry(pred, succ, c) and + not split.getKind() = predSplits.getASplit().getKind() and + not split = succSplits.getASplit() + } + + query predicate breakInvariant5( + ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, + SplitImpl split, Completion c + ) { + succSplits(pred, predSplits, succ, succSplits, c) and + split = succSplits.getASplit() and + not (split.hasSuccessor(pred, succ, c) and split = predSplits.getASplit()) and + not split.hasEntry(pred, succ, c) + } + + query predicate multipleSuccessors(Node node, SuccessorType t, Node successor) { + not node instanceof TEntryNode and + strictcount(getASuccessor(node, t)) > 1 and + successor = getASuccessor(node, t) + } +} diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplSpecific.qll new file mode 100644 index 00000000000..9c3f5276dd9 --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplSpecific.qll @@ -0,0 +1,69 @@ +private import csharp as CS +private import ControlFlowGraphImpl as Impl +private import Completion as Comp +private import Splitting as Splitting +private import SuccessorType as ST +private import semmle.code.csharp.Caching + +class ControlFlowTreeBase = Impl::ControlFlowTree::Range; + +class ControlFlowElement = CS::ControlFlowElement; + +class Completion = Comp::Completion; + +/** + * Hold if `c` represents normal evaluation of a statement or an + * expression. + */ +predicate completionIsNormal(Completion c) { c instanceof Comp::NormalCompletion } + +/** + * Hold if `c` represents simple (normal) evaluation of a statement or an + * expression. + */ +predicate completionIsSimple(Completion c) { c instanceof Comp::SimpleCompletion } + +/** Holds if `c` is a valid completion for `e`. */ +predicate completionIsValidFor(Completion c, ControlFlowElement e) { c.isValidFor(e) } + +class CfgScope = Impl::CfgScope; + +/** Gets the CFG scope for `e`. */ +CfgScope getCfgScope(ControlFlowElement e) { + Stages::ControlFlowStage::forceCachingInSameStage() and + result = e.getEnclosingCallable() +} + +predicate scopeFirst = Impl::scopeFirst/2; + +predicate scopeLast = Impl::scopeLast/3; + +/** The maximum number of splits allowed for a given node. */ +int maxSplits() { result = 5 } + +class SplitKindBase = Splitting::TSplitKind; + +class Split = Splitting::Split; + +class SuccessorType = ST::SuccessorType; + +/** Gets a successor type that matches completion `c`. */ +SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() } + +/** + * Hold if `c` represents simple (normal) evaluation of a statement or an + * expression. + */ +predicate successorTypeIsSimple(SuccessorType t) { + t instanceof ST::SuccessorTypes::NormalSuccessor +} + +/** Holds if `t` is an abnormal exit type out of a callable. */ +predicate isAbnormalExitType(SuccessorType t) { + t instanceof ST::SuccessorTypes::ExceptionSuccessor or + t instanceof ST::SuccessorTypes::ExitSuccessor +} + +class Location = CS::Location; + +class Node = CS::ControlFlow::Node; diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll index 8ca77a4775e..4d1d39de988 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/Splitting.qll @@ -11,9 +11,6 @@ private import SuccessorTypes private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow private import semmle.code.csharp.controlflow.internal.PreSsa -/** The maximum number of splits allowed for a given node. */ -private int maxSplits() { result = 5 } - cached private module Cached { private import semmle.code.csharp.Caching @@ -51,42 +48,9 @@ private module Cached { branch in [false, true] } or TLoopSplit(LoopSplitting::AnalyzableLoopStmt loop) - - cached - newtype TSplits = - TSplitsNil() or - TSplitsCons(SplitImpl head, Splits tail) { - exists( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk - | - case2aFromRank(pred, predSplits, succ, tail, c, rnk + 1) and - head = case2aSomeAtRank(pred, predSplits, succ, c, rnk) - ) - or - succEntrySplitsCons(_, _, head, tail, _) - } - - cached - string splitsToString(Splits splits) { - splits = TSplitsNil() and - result = "" - or - exists(SplitImpl head, Splits tail, string headString, string tailString | - splits = TSplitsCons(head, tail) - | - headString = head.toString() and - tailString = tail.toString() and - if tailString = "" - then result = headString - else - if headString = "" - then result = tailString - else result = headString + ", " + tailString - ) - } } -private import Cached +import Cached /** * A split for a control flow element. For example, a tag that determines how to @@ -97,127 +61,6 @@ class Split extends TSplit { string toString() { none() } } -/** - * Holds if split kinds `sk1` and `sk2` may overlap. That is, they may apply - * to at least one common control flow element inside callable `c`. - */ -private predicate overlapping(Callable c, SplitKind sk1, SplitKind sk2) { - exists(ControlFlowElement cfe | - sk1.appliesTo(cfe) and - sk2.appliesTo(cfe) and - c = cfe.getEnclosingCallable() - ) -} - -/** - * A split kind. Each control flow node can have at most one split of a - * given kind. - */ -abstract class SplitKind extends TSplitKind { - /** Gets a split of this kind. */ - SplitImpl getASplit() { result.getKind() = this } - - /** Holds if some split of this kind applies to control flow element `cfe`. */ - predicate appliesTo(ControlFlowElement cfe) { this.getASplit().appliesTo(cfe) } - - /** - * Gets a unique integer representing this split kind. The integer is used - * to represent sets of splits as ordered lists. - */ - abstract int getListOrder(); - - /** Gets the rank of this split kind among all overlapping kinds for `c`. */ - private int getRank(Callable c) { - this = rank[result](SplitKind sk | overlapping(c, this, sk) | sk order by sk.getListOrder()) - } - - /** - * Holds if this split kind is enabled for control flow element `cfe`. For - * performance reasons, the number of splits is restricted by the `maxSplits()` - * predicate. - */ - predicate isEnabled(ControlFlowElement cfe) { - this.appliesTo(cfe) and - this.getRank(cfe.getEnclosingCallable()) <= maxSplits() - } - - /** - * Gets the rank of this split kind among all the split kinds that apply to - * control flow element `cfe`. The rank is based on the order defined by - * `getListOrder()`. - */ - int getListRank(ControlFlowElement cfe) { - this.isEnabled(cfe) and - this = rank[result](SplitKind sk | sk.appliesTo(cfe) | sk order by sk.getListOrder()) - } - - /** Gets a textual representation of this split kind. */ - abstract string toString(); -} - -// This class only exists to not pollute the externally visible `Split` class -// with internal helper predicates -abstract class SplitImpl extends Split { - /** Gets the kind of this split. */ - abstract SplitKind getKind(); - - /** - * Holds if this split is entered when control passes from `pred` to `succ` with - * completion `c`. - * - * Invariant: `hasEntry(pred, succ, c) implies succ(pred, succ, c)`. - */ - abstract predicate hasEntry(ControlFlowElement pred, ControlFlowElement succ, Completion c); - - /** - * Holds if this split is entered when control passes from `scope` to the entry point - * `first`. - * - * Invariant: `hasEntryScope(scope, first) implies scopeFirst(scope, first)`. - */ - abstract predicate hasEntryScope(CfgScope scope, ControlFlowElement first); - - /** - * Holds if this split is left when control passes from `pred` to `succ` with - * completion `c`. - * - * Invariant: `hasExit(pred, succ, c) implies succ(pred, succ, c)`. - */ - abstract predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c); - - /** - * 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 scopeLast(scope, last, c)` - */ - abstract predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c); - - /** - * Holds if this split is maintained when control passes from `pred` to `succ` with - * completion `c`. - * - * Invariant: `hasSuccessor(pred, succ, c) implies succ(pred, succ, c)` - */ - abstract predicate hasSuccessor(ControlFlowElement pred, ControlFlowElement succ, Completion c); - - /** Holds if this split applies to control flow element `cfe`. */ - final predicate appliesTo(ControlFlowElement cfe) { - this.hasEntry(_, cfe, _) - or - this.hasEntryScope(_, cfe) - or - exists(ControlFlowElement pred | this.appliesTo(pred) | this.hasSuccessor(pred, cfe, _)) - } - - /** The `succ` relation restricted to predecessors `pred` that this split applies to. */ - pragma[noinline] - final predicate appliesSucc(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - this.appliesTo(pred) and - succ(pred, succ, c) - } -} - module InitializerSplitting { private import semmle.code.csharp.ExprOrStmtParent @@ -382,7 +225,7 @@ module InitializerSplitting { succ.getEnclosingCallable() = this.getConstructor() } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { this.appliesTo(last) and scopeLast(scope, last, c) and scope = this.getConstructor() @@ -499,7 +342,7 @@ module ConditionalCompletionSplitting { if c instanceof ConditionalCompletion then completion = c else any() } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { this.appliesTo(last) and scopeLast(scope, last, c) and if c instanceof ConditionalCompletion then completion = c else any() @@ -612,7 +455,7 @@ module AssertionSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { this.appliesTo(last) and last = a and scopeLast(scope, last, c) and @@ -853,7 +696,7 @@ module FinallySplitting { ) } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { scopeLast(scope, last, c) and ( exit(last, c, _) @@ -1033,7 +876,7 @@ module ExceptionHandlerSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { // Exit out from last `catch` clause (no catch clauses match) this.hasLastExit(last, c) and scopeLast(scope, last, c) @@ -1292,7 +1135,7 @@ module BooleanSplitting { ) } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { exists(PreBasicBlock bb | this.appliesToBlock(bb, c) | last = bb.getLastElement() and scopeLast(scope, last, c) @@ -1486,7 +1329,7 @@ module LoopSplitting { loop.stop(pred, succ, c) } - override predicate hasExitScope(ControlFlowElement last, CfgScope scope, Completion c) { + override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) { this.appliesToPredecessor(last, c) and scopeLast(scope, last, c) } @@ -1498,463 +1341,3 @@ module LoopSplitting { } } } - -/** - * A set of control flow node splits. The set is represented by a list of splits, - * ordered by ascending rank. - */ -class Splits extends TSplits { - /** Gets a textual representation of this set of splits. */ - string toString() { result = splitsToString(this) } - - /** Gets a split belonging to this set of splits. */ - SplitImpl getASplit() { - exists(SplitImpl head, Splits tail | this = TSplitsCons(head, tail) | - result = head - or - result = tail.getASplit() - ) - } -} - -private predicate succEntrySplitsFromRank( - CfgScope pred, ControlFlowElement succ, Splits splits, int rnk -) { - splits = TSplitsNil() and - scopeFirst(pred, succ) and - rnk = 0 - or - exists(SplitImpl head, Splits tail | succEntrySplitsCons(pred, succ, head, tail, rnk) | - splits = TSplitsCons(head, tail) - ) -} - -private predicate succEntrySplitsCons( - Callable pred, ControlFlowElement succ, SplitImpl head, Splits tail, int rnk -) { - succEntrySplitsFromRank(pred, succ, tail, rnk - 1) and - head.hasEntryScope(pred, succ) and - rnk = head.getKind().getListRank(succ) -} - -/** - * Holds if `succ` with splits `succSplits` is the first element that is executed - * when entering callable `pred`. - */ -pragma[noinline] -predicate succEntrySplits(CfgScope pred, ControlFlowElement succ, Splits succSplits, SuccessorType t) { - exists(int rnk | - scopeFirst(pred, succ) and - t instanceof NormalSuccessor and - succEntrySplitsFromRank(pred, succ, succSplits, rnk) - | - rnk = 0 and - not any(SplitImpl split).hasEntryScope(pred, succ) - or - rnk = max(SplitImpl split | split.hasEntryScope(pred, succ) | split.getKind().getListRank(succ)) - ) -} - -/** - * Holds if `pred` with splits `predSplits` can exit the enclosing callable - * `succ` with type `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 - scopeLast(succ, pred, c) and - forall(SplitImpl predSplit | predSplit = predSplits.getASplit() | - predSplit.hasExitScope(pred, succ, c) - ) - ) -} - -/** - * Provides a predicate for the successor relation with split information, - * as well as logic used to construct the type `TSplits` representing sets - * of splits. Only sets of splits that can be reached are constructed, hence - * the predicates are mutually recursive. - * - * For the successor relation - * - * ```ql - * succSplits(ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, Completion c) - * ``` - * - * the following invariants are maintained: - * - * 1. `pred` is reachable with split set `predSplits`. - * 2. For all `split` in `predSplits`: - * - If `split.hasSuccessor(pred, succ, c)` then `split` in `succSplits`. - * 3. For all `split` in `predSplits`: - * - If `split.hasExit(pred, succ, c)` and not `split.hasEntry(pred, succ, c)` then - * `split` not in `succSplits`. - * 4. For all `split` with kind not in `predSplits`: - * - If `split.hasEntry(pred, succ, c)` then `split` in `succSplits`. - * 5. For all `split` in `succSplits`: - * - `split.hasSuccessor(pred, succ, c)` and `split` in `predSplits`, or - * - `split.hasEntry(pred, succ, c)`. - * - * The algorithm divides into four cases: - * - * 1. The set of splits for the successor is the same as the set of splits - * for the predecessor: - * a) The successor is in the same `SameSplitsBlock` as the predecessor. - * b) The successor is *not* in the same `SameSplitsBlock` as the predecessor. - * 2. The set of splits for the successor is different from the set of splits - * for the predecessor: - * a) The set of splits for the successor is *maybe* non-empty. - * b) The set of splits for the successor is *always* empty. - * - * Only case 2a may introduce new sets of splits, so only predicates from - * this case are used in the definition of `TSplits`. - * - * The predicates in this module are named after the cases above. - */ -private module SuccSplits { - private predicate succInvariant1( - Reachability::SameSplitsBlock b, ControlFlowElement pred, Splits predSplits, - ControlFlowElement succ, Completion c - ) { - pred = b.getAnElement() and - b.isReachable(predSplits) and - succ(pred, succ, c) - } - - private predicate case1b0( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c - ) { - exists(Reachability::SameSplitsBlock b | - // Invariant 1 - succInvariant1(b, pred, predSplits, succ, c) - | - (succ = b.getAnElement() implies succ = b) and - // Invariant 4 - not exists(SplitImpl split | split.hasEntry(pred, succ, c)) - ) - } - - /** - * Case 1b. - * - * Invariants 1 and 4 hold in the base case, and invariants 2, 3, and 5 are - * maintained for all splits in `predSplits` (= `succSplits`), except - * possibly for the splits in `except`. - * - * The predicate is written using explicit recursion, as opposed to a `forall`, - * to avoid negative recursion. - */ - private predicate case1bForall( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, Splits except - ) { - case1b0(pred, predSplits, succ, c) and - except = predSplits - or - exists(SplitImpl split | - case1bForallCons(pred, predSplits, succ, c, split, except) and - split.hasSuccessor(pred, succ, c) - ) - } - - pragma[noinline] - private predicate case1bForallCons( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, - SplitImpl exceptHead, Splits exceptTail - ) { - case1bForall(pred, predSplits, succ, c, TSplitsCons(exceptHead, exceptTail)) - } - - private predicate case1( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c - ) { - // Case 1a - exists(Reachability::SameSplitsBlock b | succInvariant1(b, pred, predSplits, succ, c) | - succ = b.getAnElement() and - not succ = b - ) - or - // Case 1b - case1bForall(pred, predSplits, succ, c, TSplitsNil()) - } - - pragma[noinline] - private SplitImpl succInvariant1GetASplit( - Reachability::SameSplitsBlock b, ControlFlowElement pred, Splits predSplits, - ControlFlowElement succ, Completion c - ) { - succInvariant1(b, pred, predSplits, succ, c) and - result = predSplits.getASplit() - } - - private predicate case2aux( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c - ) { - exists(Reachability::SameSplitsBlock b | - succInvariant1(b, pred, predSplits, succ, c) and - (succ = b.getAnElement() implies succ = b) - | - succInvariant1GetASplit(b, pred, predSplits, succ, c).hasExit(pred, succ, c) - or - any(SplitImpl split).hasEntry(pred, succ, c) - ) - } - - /** - * Holds if `succSplits` should not inherit a split of kind `sk` from - * `predSplits`, except possibly because of a split in `except`. - * - * The predicate is written using explicit recursion, as opposed to a `forall`, - * to avoid negative recursion. - */ - private predicate case2aNoneInheritedOfKindForall( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk, - Splits except - ) { - case2aux(pred, predSplits, succ, c) and - sk.appliesTo(succ) and - except = predSplits - or - exists(Splits mid, SplitImpl split | - case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk, mid) and - mid = TSplitsCons(split, except) - | - split.getKind() = any(SplitKind sk0 | sk0 != sk and sk0.appliesTo(succ)) - or - split.hasExit(pred, succ, c) - ) - } - - pragma[nomagic] - private predicate entryOfKind( - ControlFlowElement pred, ControlFlowElement succ, Completion c, SplitImpl split, SplitKind sk - ) { - split.hasEntry(pred, succ, c) and - sk = split.getKind() - } - - /** Holds if `succSplits` should not have a split of kind `sk`. */ - pragma[nomagic] - private predicate case2aNoneOfKind( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk - ) { - // None inherited from predecessor - case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk, TSplitsNil()) and - // None newly entered into - not entryOfKind(pred, succ, c, _, sk) - } - - /** Holds if `succSplits` should not have a split of kind `sk` at rank `rnk`. */ - pragma[nomagic] - private predicate case2aNoneAtRank( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk - ) { - exists(SplitKind sk | case2aNoneOfKind(pred, predSplits, succ, c, sk) | - rnk = sk.getListRank(succ) - ) - } - - pragma[nomagic] - private SplitImpl case2auxGetAPredecessorSplit( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c - ) { - case2aux(pred, predSplits, succ, c) and - result = predSplits.getASplit() - } - - /** Gets a split that should be in `succSplits`. */ - pragma[nomagic] - private SplitImpl case2aSome( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, SplitKind sk - ) { - ( - // Inherited from predecessor - result = case2auxGetAPredecessorSplit(pred, predSplits, succ, c) and - result.hasSuccessor(pred, succ, c) - or - // Newly entered into - exists(SplitKind sk0 | - case2aNoneInheritedOfKindForall(pred, predSplits, succ, c, sk0, TSplitsNil()) - | - entryOfKind(pred, succ, c, result, sk0) - ) - ) and - sk = result.getKind() - } - - /** Gets a split that should be in `succSplits` at rank `rnk`. */ - pragma[nomagic] - SplitImpl case2aSomeAtRank( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, int rnk - ) { - exists(SplitKind sk | result = case2aSome(pred, predSplits, succ, c, sk) | - rnk = sk.getListRank(succ) - ) - } - - /** - * Case 2a. - * - * As opposed to the other cases, in this case we need to construct a new set - * of splits `succSplits`. Since this involves constructing the very IPA type, - * we cannot recurse directly over the structure of `succSplits`. Instead, we - * recurse over the ranks of all splits that *might* be in `succSplits`. - * - * - Invariant 1 holds in the base case, - * - invariant 2 holds for all splits with rank at least `rnk`, - * - invariant 3 holds for all splits in `predSplits`, - * - invariant 4 holds for all splits in `succSplits` with rank at least `rnk`, - * and - * - invariant 4 holds for all splits in `succSplits` with rank at least `rnk`. - */ - predicate case2aFromRank( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - Completion c, int rnk - ) { - case2aux(pred, predSplits, succ, c) and - succSplits = TSplitsNil() and - rnk = max(any(SplitKind sk).getListRank(succ)) + 1 - or - case2aFromRank(pred, predSplits, succ, succSplits, c, rnk + 1) and - case2aNoneAtRank(pred, predSplits, succ, c, rnk) - or - exists(Splits mid, SplitImpl split | split = case2aCons(pred, predSplits, succ, mid, c, rnk) | - succSplits = TSplitsCons(split, mid) - ) - } - - pragma[noinline] - private SplitImpl case2aCons( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - Completion c, int rnk - ) { - case2aFromRank(pred, predSplits, succ, succSplits, c, rnk + 1) and - result = case2aSomeAtRank(pred, predSplits, succ, c, rnk) - } - - /** - * Case 2b. - * - * Invariants 1, 4, and 5 hold in the base case, and invariants 2 and 3 are - * maintained for all splits in `predSplits`, except possibly for the splits - * in `except`. - * - * The predicate is written using explicit recursion, as opposed to a `forall`, - * to avoid negative recursion. - */ - private predicate case2bForall( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, Splits except - ) { - // Invariant 1 - case2aux(pred, predSplits, succ, c) and - // Invariants 4 and 5 - not any(SplitKind sk).appliesTo(succ) and - except = predSplits - or - exists(SplitImpl split | case2bForallCons(pred, predSplits, succ, c, split, except) | - // Invariants 2 and 3 - split.hasExit(pred, succ, c) - ) - } - - pragma[noinline] - private predicate case2bForallCons( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Completion c, - SplitImpl exceptHead, Splits exceptTail - ) { - case2bForall(pred, predSplits, succ, c, TSplitsCons(exceptHead, exceptTail)) - } - - private predicate case2( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - Completion c - ) { - case2aFromRank(pred, predSplits, succ, succSplits, c, 1) - or - case2bForall(pred, predSplits, succ, c, TSplitsNil()) and - succSplits = TSplitsNil() - } - - /** - * Holds if `succ` with splits `succSplits` is a successor of type `t` for `pred` - * with splits `predSplits`. - */ - predicate succSplits( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - Completion c - ) { - case1(pred, predSplits, succ, c) and - succSplits = predSplits - or - case2(pred, predSplits, succ, succSplits, c) - } -} - -import SuccSplits - -/** Provides logic for calculating reachable control flow nodes. */ -module Reachability { - /** - * Holds if `cfe` is a control flow element where the set of possible splits may - * be different from the set of possible splits for one of `cfe`'s predecessors. - * That is, `cfe` starts a new block of elements with the same set of splits. - */ - private predicate startsSplits(ControlFlowElement cfe) { - scopeFirst(_, cfe) - or - exists(SplitImpl s | - s.hasEntry(_, cfe, _) - or - s.hasExit(_, cfe, _) - ) - or - exists(ControlFlowElement pred, SplitImpl split, Completion c | succ(pred, cfe, c) | - split.appliesTo(pred) and - not split.hasSuccessor(pred, cfe, c) - ) - } - - private predicate intraSplitsSucc(ControlFlowElement pred, ControlFlowElement succ) { - succ(pred, succ, _) and - not startsSplits(succ) - } - - private predicate splitsBlockContains(ControlFlowElement start, ControlFlowElement cfe) = - fastTC(intraSplitsSucc/2)(start, cfe) - - /** - * A block of control flow elements where the set of splits is guaranteed - * to remain unchanged, represented by the first element in the block. - */ - class SameSplitsBlock extends ControlFlowElement { - SameSplitsBlock() { startsSplits(this) } - - /** Gets a control flow element in this block. */ - ControlFlowElement getAnElement() { - splitsBlockContains(this, result) - or - result = this - } - - pragma[noinline] - private SameSplitsBlock getASuccessor(Splits predSplits, Splits succSplits) { - exists(ControlFlowElement pred | pred = this.getAnElement() | - succSplits(pred, predSplits, result, succSplits, _) - ) - } - - /** - * Holds if the elements of this block are reachable from a callable entry - * point, with the splits `splits`. - */ - predicate isReachable(Splits splits) { - // Base case - succEntrySplits(_, this, splits, _) - or - // Recursive case - exists(SameSplitsBlock pred, Splits predSplits | pred.isReachable(predSplits) | - this = pred.getASuccessor(predSplits, splits) - ) - } - } -} diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 45b1b481612..1c1029ed035 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -677,7 +677,7 @@ | Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | exit Initializers | 16 | | Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | exit Initializers | 16 | | Initializers.cs:12:10:12:10 | enter M | Initializers.cs:12:10:12:10 | exit M | 22 | -| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... | 2 | +| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:16:18:20 | ... = ... | 3 | | Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:20:11:20:23 | exit NoConstructor | 9 | | Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | exit Sub | 12 | | Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | exit Sub | 9 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Consistency.expected b/csharp/ql/test/library-tests/controlflow/graph/Consistency.expected index bccab8e85a4..c025facf5ff 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Consistency.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Consistency.expected @@ -1,7 +1,7 @@ -preBasicBlockConsistency nonUniqueSetRepresentation breakInvariant2 breakInvariant3 breakInvariant4 breakInvariant5 multipleSuccessors +preBasicBlockConsistency diff --git a/csharp/ql/test/library-tests/controlflow/graph/Consistency.ql b/csharp/ql/test/library-tests/controlflow/graph/Consistency.ql index 71529e8a1f2..a6e1bf5b6f6 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Consistency.ql +++ b/csharp/ql/test/library-tests/controlflow/graph/Consistency.ql @@ -4,6 +4,7 @@ import semmle.code.csharp.controlflow.internal.PreBasicBlocks import ControlFlow import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl import semmle.code.csharp.controlflow.internal.Splitting +import Consistency predicate bbStartInconsistency(ControlFlowElement cfe) { exists(ControlFlow::BasicBlock bb | bb.getFirstNode() = cfe.getAControlFlowNode()) and @@ -49,58 +50,3 @@ query predicate preBasicBlockConsistency(ControlFlowElement cfe1, ControlFlowEle bbIntraSuccInconsistency(cfe1, cfe2) and s = "intra succ inconsistency" } - -query predicate nonUniqueSetRepresentation(Splits s1, Splits s2) { - forex(Nodes::Split s | s = s1.getASplit() | s = s2.getASplit()) and - forex(Nodes::Split s | s = s2.getASplit() | s = s1.getASplit()) and - s1 != s2 -} - -query predicate breakInvariant2( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - SplitImpl split, Completion c -) { - succSplits(pred, predSplits, succ, succSplits, c) and - split = predSplits.getASplit() and - split.hasSuccessor(pred, succ, c) and - not split = succSplits.getASplit() -} - -query predicate breakInvariant3( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - SplitImpl split, Completion c -) { - succSplits(pred, predSplits, succ, succSplits, c) and - split = predSplits.getASplit() and - split.hasExit(pred, succ, c) and - not split.hasEntry(pred, succ, c) and - split = succSplits.getASplit() -} - -query predicate breakInvariant4( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - SplitImpl split, Completion c -) { - succSplits(pred, predSplits, succ, succSplits, c) and - split.hasEntry(pred, succ, c) and - not split.getKind() = predSplits.getASplit().getKind() and - not split = succSplits.getASplit() -} - -query predicate breakInvariant5( - ControlFlowElement pred, Splits predSplits, ControlFlowElement succ, Splits succSplits, - SplitImpl split, Completion c -) { - succSplits(pred, predSplits, succ, succSplits, c) and - split = succSplits.getASplit() and - not (split.hasSuccessor(pred, succ, c) and split = predSplits.getASplit()) and - not split.hasEntry(pred, succ, c) -} - -query predicate multipleSuccessors( - ControlFlow::Node node, SuccessorType t, ControlFlow::Node successor -) { - not node instanceof ControlFlow::Nodes::EntryNode and - strictcount(node.getASuccessorByType(t)) > 1 and - successor = node.getASuccessorByType(t) -} diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index de10c0acf6f..3c690be1ec3 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -2504,6 +2504,7 @@ dominance | Initializers.cs:15:39:15:39 | access to local variable i | Initializers.cs:15:59:15:60 | "" | | Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:37:15:63 | { ..., ... } | | Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:42:15:61 | object creation of type Initializers | +| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:20:18:20 | 1 | | Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... | | Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:22:23:22:23 | this access | | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | Initializers.cs:20:11:20:23 | exit NoConstructor | @@ -6631,6 +6632,7 @@ postDominance | Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:59:15:60 | "" | | Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:39:15:39 | access to local variable i | | Initializers.cs:18:16:18:20 | ... = ... | Initializers.cs:18:20:18:20 | 1 | +| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:16 | enter H | | Initializers.cs:20:11:20:23 | exit NoConstructor | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | Initializers.cs:23:23:23:27 | ... = ... | | Initializers.cs:22:23:22:23 | this access | Initializers.cs:20:11:20:23 | enter NoConstructor | @@ -11274,7 +11276,7 @@ blockDominance | Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | enter Initializers | | Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | enter Initializers | | Initializers.cs:12:10:12:10 | enter M | Initializers.cs:12:10:12:10 | enter M | -| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:20:18:20 | 1 | +| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:16:18:16 | enter H | | Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:20:11:20:23 | enter NoConstructor | | Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | enter Sub | | Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | enter Sub | @@ -14866,7 +14868,7 @@ postBlockDominance | Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | enter Initializers | | Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | enter Initializers | | Initializers.cs:12:10:12:10 | enter M | Initializers.cs:12:10:12:10 | enter M | -| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:20:18:20 | 1 | +| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:16:18:16 | enter H | | Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:20:11:20:23 | enter NoConstructor | | Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:9:31:11 | enter Sub | | Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:9:33:11 | enter Sub | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 2441e36f62d..371b60fbd07 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -2821,6 +2821,7 @@ | Initializers.cs:15:39:15:39 | access to local variable i | Initializers.cs:15:59:15:60 | "" | semmle.label | successor | | Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:37:15:63 | { ..., ... } | semmle.label | successor | | Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:42:15:61 | object creation of type Initializers | semmle.label | successor | +| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:20:18:20 | 1 | semmle.label | successor | | Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... | semmle.label | successor | | Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:22:23:22:23 | this access | semmle.label | successor | | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | Initializers.cs:20:11:20:23 | exit NoConstructor | semmle.label | successor | From ab2bc3878929d5034cd353be0a2bbf4880ef35bb Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 19 Aug 2021 11:33:24 +0200 Subject: [PATCH 345/429] C#: Use shared logic in `NodeGraph.ql` test --- .../controlflow/graph/NodeGraph.expected | 19377 ++++++++++++---- .../controlflow/graph/NodeGraph.ql | 14 +- 2 files changed, 14457 insertions(+), 4934 deletions(-) diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 371b60fbd07..e70bb61bacc 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -1,4926 +1,14451 @@ -| AccessorCalls.cs:5:23:5:25 | enter get_Item | AccessorCalls.cs:5:30:5:30 | access to parameter i | semmle.label | successor | -| AccessorCalls.cs:5:23:5:25 | exit get_Item (normal) | AccessorCalls.cs:5:23:5:25 | exit get_Item | semmle.label | successor | -| AccessorCalls.cs:5:30:5:30 | access to parameter i | AccessorCalls.cs:5:23:5:25 | exit get_Item (normal) | semmle.label | successor | -| AccessorCalls.cs:5:33:5:35 | enter set_Item | AccessorCalls.cs:5:37:5:39 | {...} | semmle.label | successor | -| AccessorCalls.cs:5:33:5:35 | exit set_Item (normal) | AccessorCalls.cs:5:33:5:35 | exit set_Item | semmle.label | successor | -| AccessorCalls.cs:5:37:5:39 | {...} | AccessorCalls.cs:5:33:5:35 | exit set_Item (normal) | semmle.label | successor | -| AccessorCalls.cs:7:32:7:34 | enter add_Event | AccessorCalls.cs:7:36:7:38 | {...} | semmle.label | successor | -| AccessorCalls.cs:7:32:7:34 | exit add_Event (normal) | AccessorCalls.cs:7:32:7:34 | exit add_Event | semmle.label | successor | -| AccessorCalls.cs:7:36:7:38 | {...} | AccessorCalls.cs:7:32:7:34 | exit add_Event (normal) | semmle.label | successor | -| AccessorCalls.cs:7:40:7:45 | enter remove_Event | AccessorCalls.cs:7:47:7:49 | {...} | semmle.label | successor | -| AccessorCalls.cs:7:40:7:45 | exit remove_Event (normal) | AccessorCalls.cs:7:40:7:45 | exit remove_Event | semmle.label | successor | -| AccessorCalls.cs:7:47:7:49 | {...} | AccessorCalls.cs:7:40:7:45 | exit remove_Event (normal) | semmle.label | successor | -| AccessorCalls.cs:10:10:10:11 | enter M1 | AccessorCalls.cs:11:5:17:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:10:10:10:11 | exit M1 (normal) | AccessorCalls.cs:10:10:10:11 | exit M1 | semmle.label | successor | -| AccessorCalls.cs:11:5:17:5 | {...} | AccessorCalls.cs:12:9:12:32 | ...; | semmle.label | successor | -| AccessorCalls.cs:12:9:12:12 | this access | AccessorCalls.cs:12:22:12:25 | this access | semmle.label | successor | -| AccessorCalls.cs:12:9:12:31 | ... = ... | AccessorCalls.cs:13:9:13:30 | ...; | semmle.label | successor | -| AccessorCalls.cs:12:9:12:32 | ...; | AccessorCalls.cs:12:9:12:12 | this access | semmle.label | successor | -| AccessorCalls.cs:12:22:12:25 | this access | AccessorCalls.cs:12:22:12:31 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:12:22:12:31 | access to field Field | AccessorCalls.cs:12:9:12:31 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:13:9:13:12 | this access | AccessorCalls.cs:13:21:13:24 | this access | semmle.label | successor | -| AccessorCalls.cs:13:9:13:17 | access to property Prop | AccessorCalls.cs:13:9:13:29 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:13:9:13:29 | ... = ... | AccessorCalls.cs:14:9:14:26 | ...; | semmle.label | successor | -| AccessorCalls.cs:13:9:13:30 | ...; | AccessorCalls.cs:13:9:13:12 | this access | semmle.label | successor | -| AccessorCalls.cs:13:21:13:24 | this access | AccessorCalls.cs:13:21:13:29 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:13:21:13:29 | access to property Prop | AccessorCalls.cs:13:9:13:17 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:14:9:14:12 | this access | AccessorCalls.cs:14:14:14:14 | 0 | semmle.label | successor | -| AccessorCalls.cs:14:9:14:15 | access to indexer | AccessorCalls.cs:14:9:14:25 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:14:9:14:25 | ... = ... | AccessorCalls.cs:15:9:15:24 | ...; | semmle.label | successor | -| AccessorCalls.cs:14:9:14:26 | ...; | AccessorCalls.cs:14:9:14:12 | this access | semmle.label | successor | -| AccessorCalls.cs:14:14:14:14 | 0 | AccessorCalls.cs:14:19:14:22 | this access | semmle.label | successor | -| AccessorCalls.cs:14:19:14:22 | this access | AccessorCalls.cs:14:24:14:24 | 1 | semmle.label | successor | -| AccessorCalls.cs:14:19:14:25 | access to indexer | AccessorCalls.cs:14:9:14:15 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:14:24:14:24 | 1 | AccessorCalls.cs:14:19:14:25 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:15:9:15:12 | this access | AccessorCalls.cs:15:23:15:23 | access to parameter e | semmle.label | successor | -| AccessorCalls.cs:15:9:15:18 | access to event Event | AccessorCalls.cs:15:9:15:23 | ... += ... | semmle.label | successor | -| AccessorCalls.cs:15:9:15:23 | ... += ... | AccessorCalls.cs:16:9:16:24 | ...; | semmle.label | successor | -| AccessorCalls.cs:15:9:15:24 | ...; | AccessorCalls.cs:15:9:15:12 | this access | semmle.label | successor | -| AccessorCalls.cs:15:23:15:23 | access to parameter e | AccessorCalls.cs:15:9:15:18 | access to event Event | semmle.label | successor | -| AccessorCalls.cs:16:9:16:12 | this access | AccessorCalls.cs:16:23:16:23 | access to parameter e | semmle.label | successor | -| AccessorCalls.cs:16:9:16:18 | access to event Event | AccessorCalls.cs:16:9:16:23 | ... -= ... | semmle.label | successor | -| AccessorCalls.cs:16:9:16:23 | ... -= ... | AccessorCalls.cs:10:10:10:11 | exit M1 (normal) | semmle.label | successor | -| AccessorCalls.cs:16:9:16:24 | ...; | AccessorCalls.cs:16:9:16:12 | this access | semmle.label | successor | -| AccessorCalls.cs:16:23:16:23 | access to parameter e | AccessorCalls.cs:16:9:16:18 | access to event Event | semmle.label | successor | -| AccessorCalls.cs:19:10:19:11 | enter M2 | AccessorCalls.cs:20:5:26:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:19:10:19:11 | exit M2 (normal) | AccessorCalls.cs:19:10:19:11 | exit M2 | semmle.label | successor | -| AccessorCalls.cs:20:5:26:5 | {...} | AccessorCalls.cs:21:9:21:36 | ...; | semmle.label | successor | -| AccessorCalls.cs:21:9:21:12 | this access | AccessorCalls.cs:21:9:21:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:21:9:21:14 | access to field x | AccessorCalls.cs:21:24:21:27 | this access | semmle.label | successor | -| AccessorCalls.cs:21:9:21:35 | ... = ... | AccessorCalls.cs:22:9:22:34 | ...; | semmle.label | successor | -| AccessorCalls.cs:21:9:21:36 | ...; | AccessorCalls.cs:21:9:21:12 | this access | semmle.label | successor | -| AccessorCalls.cs:21:24:21:27 | this access | AccessorCalls.cs:21:24:21:29 | access to field x | semmle.label | successor | -| AccessorCalls.cs:21:24:21:29 | access to field x | AccessorCalls.cs:21:24:21:35 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:21:24:21:35 | access to field Field | AccessorCalls.cs:21:9:21:35 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:22:9:22:12 | this access | AccessorCalls.cs:22:9:22:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:22:9:22:14 | access to field x | AccessorCalls.cs:22:23:22:26 | this access | semmle.label | successor | -| AccessorCalls.cs:22:9:22:19 | access to property Prop | AccessorCalls.cs:22:9:22:33 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:22:9:22:33 | ... = ... | AccessorCalls.cs:23:9:23:30 | ...; | semmle.label | successor | -| AccessorCalls.cs:22:9:22:34 | ...; | AccessorCalls.cs:22:9:22:12 | this access | semmle.label | successor | -| AccessorCalls.cs:22:23:22:26 | this access | AccessorCalls.cs:22:23:22:28 | access to field x | semmle.label | successor | -| AccessorCalls.cs:22:23:22:28 | access to field x | AccessorCalls.cs:22:23:22:33 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:22:23:22:33 | access to property Prop | AccessorCalls.cs:22:9:22:19 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:23:9:23:12 | this access | AccessorCalls.cs:23:9:23:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:23:9:23:14 | access to field x | AccessorCalls.cs:23:16:23:16 | 0 | semmle.label | successor | -| AccessorCalls.cs:23:9:23:17 | access to indexer | AccessorCalls.cs:23:9:23:29 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:23:9:23:29 | ... = ... | AccessorCalls.cs:24:9:24:26 | ...; | semmle.label | successor | -| AccessorCalls.cs:23:9:23:30 | ...; | AccessorCalls.cs:23:9:23:12 | this access | semmle.label | successor | -| AccessorCalls.cs:23:16:23:16 | 0 | AccessorCalls.cs:23:21:23:24 | this access | semmle.label | successor | -| AccessorCalls.cs:23:21:23:24 | this access | AccessorCalls.cs:23:21:23:26 | access to field x | semmle.label | successor | -| AccessorCalls.cs:23:21:23:26 | access to field x | AccessorCalls.cs:23:28:23:28 | 1 | semmle.label | successor | -| AccessorCalls.cs:23:21:23:29 | access to indexer | AccessorCalls.cs:23:9:23:17 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:23:28:23:28 | 1 | AccessorCalls.cs:23:21:23:29 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:24:9:24:12 | this access | AccessorCalls.cs:24:9:24:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:24:9:24:14 | access to field x | AccessorCalls.cs:24:25:24:25 | access to parameter e | semmle.label | successor | -| AccessorCalls.cs:24:9:24:20 | access to event Event | AccessorCalls.cs:24:9:24:25 | ... += ... | semmle.label | successor | -| AccessorCalls.cs:24:9:24:25 | ... += ... | AccessorCalls.cs:25:9:25:26 | ...; | semmle.label | successor | -| AccessorCalls.cs:24:9:24:26 | ...; | AccessorCalls.cs:24:9:24:12 | this access | semmle.label | successor | -| AccessorCalls.cs:24:25:24:25 | access to parameter e | AccessorCalls.cs:24:9:24:20 | access to event Event | semmle.label | successor | -| AccessorCalls.cs:25:9:25:12 | this access | AccessorCalls.cs:25:9:25:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:25:9:25:14 | access to field x | AccessorCalls.cs:25:25:25:25 | access to parameter e | semmle.label | successor | -| AccessorCalls.cs:25:9:25:20 | access to event Event | AccessorCalls.cs:25:9:25:25 | ... -= ... | semmle.label | successor | -| AccessorCalls.cs:25:9:25:25 | ... -= ... | AccessorCalls.cs:19:10:19:11 | exit M2 (normal) | semmle.label | successor | -| AccessorCalls.cs:25:9:25:26 | ...; | AccessorCalls.cs:25:9:25:12 | this access | semmle.label | successor | -| AccessorCalls.cs:25:25:25:25 | access to parameter e | AccessorCalls.cs:25:9:25:20 | access to event Event | semmle.label | successor | -| AccessorCalls.cs:28:10:28:11 | enter M3 | AccessorCalls.cs:29:5:33:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:28:10:28:11 | exit M3 (normal) | AccessorCalls.cs:28:10:28:11 | exit M3 | semmle.label | successor | -| AccessorCalls.cs:29:5:33:5 | {...} | AccessorCalls.cs:30:9:30:21 | ...; | semmle.label | successor | -| AccessorCalls.cs:30:9:30:12 | this access | AccessorCalls.cs:30:9:30:18 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:30:9:30:18 | access to field Field | AccessorCalls.cs:30:9:30:20 | ...++ | semmle.label | successor | -| AccessorCalls.cs:30:9:30:20 | ...++ | AccessorCalls.cs:31:9:31:20 | ...; | semmle.label | successor | -| AccessorCalls.cs:30:9:30:21 | ...; | AccessorCalls.cs:30:9:30:12 | this access | semmle.label | successor | -| AccessorCalls.cs:31:9:31:12 | this access | AccessorCalls.cs:31:9:31:17 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:31:9:31:17 | access to property Prop | AccessorCalls.cs:31:9:31:19 | ...++ | semmle.label | successor | -| AccessorCalls.cs:31:9:31:19 | ...++ | AccessorCalls.cs:32:9:32:18 | ...; | semmle.label | successor | -| AccessorCalls.cs:31:9:31:20 | ...; | AccessorCalls.cs:31:9:31:12 | this access | semmle.label | successor | -| AccessorCalls.cs:32:9:32:12 | this access | AccessorCalls.cs:32:14:32:14 | 0 | semmle.label | successor | -| AccessorCalls.cs:32:9:32:15 | access to indexer | AccessorCalls.cs:32:9:32:17 | ...++ | semmle.label | successor | -| AccessorCalls.cs:32:9:32:17 | ...++ | AccessorCalls.cs:28:10:28:11 | exit M3 (normal) | semmle.label | successor | -| AccessorCalls.cs:32:9:32:18 | ...; | AccessorCalls.cs:32:9:32:12 | this access | semmle.label | successor | -| AccessorCalls.cs:32:14:32:14 | 0 | AccessorCalls.cs:32:9:32:15 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:35:10:35:11 | enter M4 | AccessorCalls.cs:36:5:40:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:35:10:35:11 | exit M4 (normal) | AccessorCalls.cs:35:10:35:11 | exit M4 | semmle.label | successor | -| AccessorCalls.cs:36:5:40:5 | {...} | AccessorCalls.cs:37:9:37:23 | ...; | semmle.label | successor | -| AccessorCalls.cs:37:9:37:12 | this access | AccessorCalls.cs:37:9:37:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:37:9:37:14 | access to field x | AccessorCalls.cs:37:9:37:20 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:37:9:37:20 | access to field Field | AccessorCalls.cs:37:9:37:22 | ...++ | semmle.label | successor | -| AccessorCalls.cs:37:9:37:22 | ...++ | AccessorCalls.cs:38:9:38:22 | ...; | semmle.label | successor | -| AccessorCalls.cs:37:9:37:23 | ...; | AccessorCalls.cs:37:9:37:12 | this access | semmle.label | successor | -| AccessorCalls.cs:38:9:38:12 | this access | AccessorCalls.cs:38:9:38:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:38:9:38:14 | access to field x | AccessorCalls.cs:38:9:38:19 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:38:9:38:19 | access to property Prop | AccessorCalls.cs:38:9:38:21 | ...++ | semmle.label | successor | -| AccessorCalls.cs:38:9:38:21 | ...++ | AccessorCalls.cs:39:9:39:20 | ...; | semmle.label | successor | -| AccessorCalls.cs:38:9:38:22 | ...; | AccessorCalls.cs:38:9:38:12 | this access | semmle.label | successor | -| AccessorCalls.cs:39:9:39:12 | this access | AccessorCalls.cs:39:9:39:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:39:9:39:14 | access to field x | AccessorCalls.cs:39:16:39:16 | 0 | semmle.label | successor | -| AccessorCalls.cs:39:9:39:17 | access to indexer | AccessorCalls.cs:39:9:39:19 | ...++ | semmle.label | successor | -| AccessorCalls.cs:39:9:39:19 | ...++ | AccessorCalls.cs:35:10:35:11 | exit M4 (normal) | semmle.label | successor | -| AccessorCalls.cs:39:9:39:20 | ...; | AccessorCalls.cs:39:9:39:12 | this access | semmle.label | successor | -| AccessorCalls.cs:39:16:39:16 | 0 | AccessorCalls.cs:39:9:39:17 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:42:10:42:11 | enter M5 | AccessorCalls.cs:43:5:47:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:42:10:42:11 | exit M5 (normal) | AccessorCalls.cs:42:10:42:11 | exit M5 | semmle.label | successor | -| AccessorCalls.cs:43:5:47:5 | {...} | AccessorCalls.cs:44:9:44:33 | ...; | semmle.label | successor | -| AccessorCalls.cs:44:9:44:12 | this access | AccessorCalls.cs:44:9:44:12 | this access | semmle.label | successor | -| AccessorCalls.cs:44:9:44:12 | this access | AccessorCalls.cs:44:9:44:18 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:44:9:44:18 | access to field Field | AccessorCalls.cs:44:23:44:26 | this access | semmle.label | successor | -| AccessorCalls.cs:44:9:44:32 | ... + ... | AccessorCalls.cs:44:9:44:32 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:44:9:44:32 | ... = ... | AccessorCalls.cs:45:9:45:31 | ...; | semmle.label | successor | -| AccessorCalls.cs:44:9:44:33 | ...; | AccessorCalls.cs:44:9:44:12 | this access | semmle.label | successor | -| AccessorCalls.cs:44:23:44:26 | this access | AccessorCalls.cs:44:23:44:32 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:44:23:44:32 | access to field Field | AccessorCalls.cs:44:9:44:32 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:45:9:45:12 | this access | AccessorCalls.cs:45:9:45:12 | this access | semmle.label | successor | -| AccessorCalls.cs:45:9:45:12 | this access | AccessorCalls.cs:45:9:45:17 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:45:9:45:17 | access to property Prop | AccessorCalls.cs:45:9:45:30 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:45:9:45:17 | access to property Prop | AccessorCalls.cs:45:22:45:25 | this access | semmle.label | successor | -| AccessorCalls.cs:45:9:45:30 | ... + ... | AccessorCalls.cs:45:9:45:17 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:45:9:45:30 | ... = ... | AccessorCalls.cs:46:9:46:27 | ...; | semmle.label | successor | -| AccessorCalls.cs:45:9:45:31 | ...; | AccessorCalls.cs:45:9:45:12 | this access | semmle.label | successor | -| AccessorCalls.cs:45:22:45:25 | this access | AccessorCalls.cs:45:22:45:30 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:45:22:45:30 | access to property Prop | AccessorCalls.cs:45:9:45:30 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:46:9:46:12 | this access | AccessorCalls.cs:46:14:46:14 | 0 | semmle.label | successor | -| AccessorCalls.cs:46:9:46:12 | this access | AccessorCalls.cs:46:14:46:14 | 0 | semmle.label | successor | -| AccessorCalls.cs:46:9:46:15 | access to indexer | AccessorCalls.cs:46:9:46:26 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:46:9:46:15 | access to indexer | AccessorCalls.cs:46:20:46:23 | this access | semmle.label | successor | -| AccessorCalls.cs:46:9:46:26 | ... + ... | AccessorCalls.cs:46:9:46:15 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:46:9:46:26 | ... = ... | AccessorCalls.cs:42:10:42:11 | exit M5 (normal) | semmle.label | successor | -| AccessorCalls.cs:46:9:46:27 | ...; | AccessorCalls.cs:46:9:46:12 | this access | semmle.label | successor | -| AccessorCalls.cs:46:14:46:14 | 0 | AccessorCalls.cs:46:9:46:12 | this access | semmle.label | successor | -| AccessorCalls.cs:46:14:46:14 | 0 | AccessorCalls.cs:46:9:46:15 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:46:20:46:23 | this access | AccessorCalls.cs:46:25:46:25 | 0 | semmle.label | successor | -| AccessorCalls.cs:46:20:46:26 | access to indexer | AccessorCalls.cs:46:9:46:26 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:46:25:46:25 | 0 | AccessorCalls.cs:46:20:46:26 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:49:10:49:11 | enter M6 | AccessorCalls.cs:50:5:54:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:49:10:49:11 | exit M6 (normal) | AccessorCalls.cs:49:10:49:11 | exit M6 | semmle.label | successor | -| AccessorCalls.cs:50:5:54:5 | {...} | AccessorCalls.cs:51:9:51:37 | ...; | semmle.label | successor | -| AccessorCalls.cs:51:9:51:12 | this access | AccessorCalls.cs:51:9:51:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:51:9:51:12 | this access | AccessorCalls.cs:51:9:51:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:51:9:51:14 | access to field x | AccessorCalls.cs:51:9:51:12 | this access | semmle.label | successor | -| AccessorCalls.cs:51:9:51:14 | access to field x | AccessorCalls.cs:51:9:51:20 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:51:9:51:20 | access to field Field | AccessorCalls.cs:51:25:51:28 | this access | semmle.label | successor | -| AccessorCalls.cs:51:9:51:36 | ... + ... | AccessorCalls.cs:51:9:51:36 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:51:9:51:36 | ... = ... | AccessorCalls.cs:52:9:52:35 | ...; | semmle.label | successor | -| AccessorCalls.cs:51:9:51:37 | ...; | AccessorCalls.cs:51:9:51:12 | this access | semmle.label | successor | -| AccessorCalls.cs:51:25:51:28 | this access | AccessorCalls.cs:51:25:51:30 | access to field x | semmle.label | successor | -| AccessorCalls.cs:51:25:51:30 | access to field x | AccessorCalls.cs:51:25:51:36 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:51:25:51:36 | access to field Field | AccessorCalls.cs:51:9:51:36 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:52:9:52:12 | this access | AccessorCalls.cs:52:9:52:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:52:9:52:12 | this access | AccessorCalls.cs:52:9:52:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:52:9:52:14 | access to field x | AccessorCalls.cs:52:9:52:12 | this access | semmle.label | successor | -| AccessorCalls.cs:52:9:52:14 | access to field x | AccessorCalls.cs:52:9:52:19 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:52:9:52:19 | access to property Prop | AccessorCalls.cs:52:9:52:34 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:52:9:52:19 | access to property Prop | AccessorCalls.cs:52:24:52:27 | this access | semmle.label | successor | -| AccessorCalls.cs:52:9:52:34 | ... + ... | AccessorCalls.cs:52:9:52:19 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:52:9:52:34 | ... = ... | AccessorCalls.cs:53:9:53:31 | ...; | semmle.label | successor | -| AccessorCalls.cs:52:9:52:35 | ...; | AccessorCalls.cs:52:9:52:12 | this access | semmle.label | successor | -| AccessorCalls.cs:52:24:52:27 | this access | AccessorCalls.cs:52:24:52:29 | access to field x | semmle.label | successor | -| AccessorCalls.cs:52:24:52:29 | access to field x | AccessorCalls.cs:52:24:52:34 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:52:24:52:34 | access to property Prop | AccessorCalls.cs:52:9:52:34 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:53:9:53:12 | this access | AccessorCalls.cs:53:9:53:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:53:9:53:12 | this access | AccessorCalls.cs:53:9:53:14 | access to field x | semmle.label | successor | -| AccessorCalls.cs:53:9:53:14 | access to field x | AccessorCalls.cs:53:16:53:16 | 0 | semmle.label | successor | -| AccessorCalls.cs:53:9:53:14 | access to field x | AccessorCalls.cs:53:16:53:16 | 0 | semmle.label | successor | -| AccessorCalls.cs:53:9:53:17 | access to indexer | AccessorCalls.cs:53:9:53:30 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:53:9:53:17 | access to indexer | AccessorCalls.cs:53:22:53:25 | this access | semmle.label | successor | -| AccessorCalls.cs:53:9:53:30 | ... + ... | AccessorCalls.cs:53:9:53:17 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:53:9:53:30 | ... = ... | AccessorCalls.cs:49:10:49:11 | exit M6 (normal) | semmle.label | successor | -| AccessorCalls.cs:53:9:53:31 | ...; | AccessorCalls.cs:53:9:53:12 | this access | semmle.label | successor | -| AccessorCalls.cs:53:16:53:16 | 0 | AccessorCalls.cs:53:9:53:12 | this access | semmle.label | successor | -| AccessorCalls.cs:53:16:53:16 | 0 | AccessorCalls.cs:53:9:53:17 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:53:22:53:25 | this access | AccessorCalls.cs:53:22:53:27 | access to field x | semmle.label | successor | -| AccessorCalls.cs:53:22:53:27 | access to field x | AccessorCalls.cs:53:29:53:29 | 0 | semmle.label | successor | -| AccessorCalls.cs:53:22:53:30 | access to indexer | AccessorCalls.cs:53:9:53:30 | ... + ... | semmle.label | successor | -| AccessorCalls.cs:53:29:53:29 | 0 | AccessorCalls.cs:53:22:53:30 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:56:10:56:11 | enter M7 | AccessorCalls.cs:57:5:59:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:56:10:56:11 | exit M7 (normal) | AccessorCalls.cs:56:10:56:11 | exit M7 | semmle.label | successor | -| AccessorCalls.cs:57:5:59:5 | {...} | AccessorCalls.cs:58:9:58:86 | ...; | semmle.label | successor | -| AccessorCalls.cs:58:9:58:45 | (..., ...) | AccessorCalls.cs:58:50:58:53 | this access | semmle.label | successor | -| AccessorCalls.cs:58:9:58:85 | ... = ... | AccessorCalls.cs:56:10:56:11 | exit M7 (normal) | semmle.label | successor | -| AccessorCalls.cs:58:9:58:86 | ...; | AccessorCalls.cs:58:10:58:13 | this access | semmle.label | successor | -| AccessorCalls.cs:58:10:58:13 | this access | AccessorCalls.cs:58:22:58:25 | this access | semmle.label | successor | -| AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:37:58:40 | this access | semmle.label | successor | -| AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:37:58:43 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:9:58:45 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:42:58:42 | 0 | semmle.label | successor | -| AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:9:58:85 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:33:58:44 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:58:49:58:85 | (..., ...) | AccessorCalls.cs:58:22:58:30 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:58:50:58:53 | this access | AccessorCalls.cs:58:50:58:59 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:58:50:58:59 | access to field Field | AccessorCalls.cs:58:62:58:65 | this access | semmle.label | successor | -| AccessorCalls.cs:58:62:58:65 | this access | AccessorCalls.cs:58:62:58:70 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:58:62:58:70 | access to property Prop | AccessorCalls.cs:58:74:58:74 | 0 | semmle.label | successor | -| AccessorCalls.cs:58:73:58:84 | (..., ...) | AccessorCalls.cs:58:49:58:85 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:58:74:58:74 | 0 | AccessorCalls.cs:58:77:58:80 | this access | semmle.label | successor | -| AccessorCalls.cs:58:77:58:80 | this access | AccessorCalls.cs:58:82:58:82 | 1 | semmle.label | successor | -| AccessorCalls.cs:58:77:58:83 | access to indexer | AccessorCalls.cs:58:73:58:84 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:58:82:58:82 | 1 | AccessorCalls.cs:58:77:58:83 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:61:10:61:11 | enter M8 | AccessorCalls.cs:62:5:64:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:61:10:61:11 | exit M8 (normal) | AccessorCalls.cs:61:10:61:11 | exit M8 | semmle.label | successor | -| AccessorCalls.cs:62:5:64:5 | {...} | AccessorCalls.cs:63:9:63:98 | ...; | semmle.label | successor | -| AccessorCalls.cs:63:9:63:51 | (..., ...) | AccessorCalls.cs:63:56:63:59 | this access | semmle.label | successor | -| AccessorCalls.cs:63:9:63:97 | ... = ... | AccessorCalls.cs:61:10:61:11 | exit M8 (normal) | semmle.label | successor | -| AccessorCalls.cs:63:9:63:98 | ...; | AccessorCalls.cs:63:10:63:13 | this access | semmle.label | successor | -| AccessorCalls.cs:63:10:63:13 | this access | AccessorCalls.cs:63:10:63:15 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:10:63:15 | access to field x | AccessorCalls.cs:63:24:63:27 | this access | semmle.label | successor | -| AccessorCalls.cs:63:24:63:27 | this access | AccessorCalls.cs:63:24:63:29 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:24:63:29 | access to field x | AccessorCalls.cs:63:41:63:44 | this access | semmle.label | successor | -| AccessorCalls.cs:63:24:63:34 | access to property Prop | AccessorCalls.cs:63:41:63:49 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:63:37:63:50 | (..., ...) | AccessorCalls.cs:63:9:63:51 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:63:41:63:44 | this access | AccessorCalls.cs:63:41:63:46 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:41:63:46 | access to field x | AccessorCalls.cs:63:48:63:48 | 0 | semmle.label | successor | -| AccessorCalls.cs:63:41:63:49 | access to indexer | AccessorCalls.cs:63:9:63:97 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:63:48:63:48 | 0 | AccessorCalls.cs:63:37:63:50 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:63:55:63:97 | (..., ...) | AccessorCalls.cs:63:24:63:34 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:63:56:63:59 | this access | AccessorCalls.cs:63:56:63:61 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:56:63:61 | access to field x | AccessorCalls.cs:63:56:63:67 | access to field Field | semmle.label | successor | -| AccessorCalls.cs:63:56:63:67 | access to field Field | AccessorCalls.cs:63:70:63:73 | this access | semmle.label | successor | -| AccessorCalls.cs:63:70:63:73 | this access | AccessorCalls.cs:63:70:63:75 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:70:63:75 | access to field x | AccessorCalls.cs:63:70:63:80 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:63:70:63:80 | access to property Prop | AccessorCalls.cs:63:84:63:84 | 0 | semmle.label | successor | -| AccessorCalls.cs:63:83:63:96 | (..., ...) | AccessorCalls.cs:63:55:63:97 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:63:84:63:84 | 0 | AccessorCalls.cs:63:87:63:90 | this access | semmle.label | successor | -| AccessorCalls.cs:63:87:63:90 | this access | AccessorCalls.cs:63:87:63:92 | access to field x | semmle.label | successor | -| AccessorCalls.cs:63:87:63:92 | access to field x | AccessorCalls.cs:63:94:63:94 | 1 | semmle.label | successor | -| AccessorCalls.cs:63:87:63:95 | access to indexer | AccessorCalls.cs:63:83:63:96 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:63:94:63:94 | 1 | AccessorCalls.cs:63:87:63:95 | access to indexer | semmle.label | successor | -| AccessorCalls.cs:66:10:66:11 | enter M9 | AccessorCalls.cs:67:5:74:5 | {...} | semmle.label | successor | -| AccessorCalls.cs:66:10:66:11 | exit M9 (normal) | AccessorCalls.cs:66:10:66:11 | exit M9 | semmle.label | successor | -| AccessorCalls.cs:67:5:74:5 | {...} | AccessorCalls.cs:68:9:68:22 | ... ...; | semmle.label | successor | -| AccessorCalls.cs:68:9:68:22 | ... ...; | AccessorCalls.cs:68:21:68:21 | access to parameter o | semmle.label | successor | -| AccessorCalls.cs:68:17:68:21 | dynamic d = ... | AccessorCalls.cs:69:9:69:36 | ...; | semmle.label | successor | -| AccessorCalls.cs:68:21:68:21 | access to parameter o | AccessorCalls.cs:68:17:68:21 | dynamic d = ... | semmle.label | successor | -| AccessorCalls.cs:69:9:69:9 | access to local variable d | AccessorCalls.cs:69:24:69:24 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 | AccessorCalls.cs:69:9:69:35 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:69:9:69:35 | ... = ... | AccessorCalls.cs:70:9:70:22 | ...; | semmle.label | successor | -| AccessorCalls.cs:69:9:69:36 | ...; | AccessorCalls.cs:69:9:69:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:69:24:69:24 | access to local variable d | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 | semmle.label | successor | -| AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 | AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 | semmle.label | successor | -| AccessorCalls.cs:70:9:70:9 | access to local variable d | AccessorCalls.cs:70:9:70:19 | dynamic access to member MaybeProp | semmle.label | successor | -| AccessorCalls.cs:70:9:70:19 | dynamic access to member MaybeProp | AccessorCalls.cs:70:9:70:21 | dynamic call to operator ++ | semmle.label | successor | -| AccessorCalls.cs:70:9:70:21 | dynamic call to operator ++ | AccessorCalls.cs:71:9:71:26 | ...; | semmle.label | successor | -| AccessorCalls.cs:70:9:70:22 | ...; | AccessorCalls.cs:70:9:70:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | semmle.label | successor | -| AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:9:71:25 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:25:71:25 | access to parameter e | semmle.label | successor | -| AccessorCalls.cs:71:9:71:25 | ... = ... | AccessorCalls.cs:72:9:72:21 | ...; | semmle.label | successor | -| AccessorCalls.cs:71:9:71:25 | dynamic call to operator + | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | semmle.label | successor | -| AccessorCalls.cs:71:9:71:26 | ...; | AccessorCalls.cs:71:9:71:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:71:25:71:25 | access to parameter e | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + | semmle.label | successor | -| AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:11:72:11 | 0 | semmle.label | successor | -| AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:11:72:11 | 0 | semmle.label | successor | -| AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:9:72:20 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:17:72:17 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:72:9:72:20 | ... = ... | AccessorCalls.cs:73:9:73:84 | ...; | semmle.label | successor | -| AccessorCalls.cs:72:9:72:20 | dynamic call to operator + | AccessorCalls.cs:72:9:72:12 | dynamic access to element | semmle.label | successor | -| AccessorCalls.cs:72:9:72:21 | ...; | AccessorCalls.cs:72:9:72:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:72:11:72:11 | 0 | AccessorCalls.cs:72:9:72:9 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:72:11:72:11 | 0 | AccessorCalls.cs:72:9:72:12 | dynamic access to element | semmle.label | successor | -| AccessorCalls.cs:72:17:72:17 | access to local variable d | AccessorCalls.cs:72:19:72:19 | 1 | semmle.label | successor | -| AccessorCalls.cs:72:17:72:20 | dynamic access to element | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + | semmle.label | successor | -| AccessorCalls.cs:72:19:72:19 | 1 | AccessorCalls.cs:72:17:72:20 | dynamic access to element | semmle.label | successor | -| AccessorCalls.cs:73:9:73:44 | (..., ...) | AccessorCalls.cs:73:49:73:49 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:73:9:73:83 | ... = ... | AccessorCalls.cs:66:10:66:11 | exit M9 (normal) | semmle.label | successor | -| AccessorCalls.cs:73:9:73:84 | ...; | AccessorCalls.cs:73:10:73:10 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:73:10:73:10 | access to local variable d | AccessorCalls.cs:73:24:73:27 | this access | semmle.label | successor | -| AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 | AccessorCalls.cs:73:24:73:32 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:73:24:73:27 | this access | AccessorCalls.cs:73:39:73:39 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:73:24:73:32 | access to property Prop | AccessorCalls.cs:73:39:73:42 | dynamic access to element | semmle.label | successor | -| AccessorCalls.cs:73:35:73:43 | (..., ...) | AccessorCalls.cs:73:9:73:44 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:73:39:73:39 | access to local variable d | AccessorCalls.cs:73:41:73:41 | 0 | semmle.label | successor | -| AccessorCalls.cs:73:39:73:42 | dynamic access to element | AccessorCalls.cs:73:9:73:83 | ... = ... | semmle.label | successor | -| AccessorCalls.cs:73:41:73:41 | 0 | AccessorCalls.cs:73:35:73:43 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:73:48:73:83 | (..., ...) | AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 | semmle.label | successor | -| AccessorCalls.cs:73:49:73:49 | access to local variable d | AccessorCalls.cs:73:49:73:60 | dynamic access to member MaybeProp1 | semmle.label | successor | -| AccessorCalls.cs:73:49:73:60 | dynamic access to member MaybeProp1 | AccessorCalls.cs:73:63:73:66 | this access | semmle.label | successor | -| AccessorCalls.cs:73:63:73:66 | this access | AccessorCalls.cs:73:63:73:71 | access to property Prop | semmle.label | successor | -| AccessorCalls.cs:73:63:73:71 | access to property Prop | AccessorCalls.cs:73:75:73:75 | 0 | semmle.label | successor | -| AccessorCalls.cs:73:74:73:82 | (..., ...) | AccessorCalls.cs:73:48:73:83 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:73:75:73:75 | 0 | AccessorCalls.cs:73:78:73:78 | access to local variable d | semmle.label | successor | -| AccessorCalls.cs:73:78:73:78 | access to local variable d | AccessorCalls.cs:73:80:73:80 | 1 | semmle.label | successor | -| AccessorCalls.cs:73:78:73:81 | dynamic access to element | AccessorCalls.cs:73:74:73:82 | (..., ...) | semmle.label | successor | -| AccessorCalls.cs:73:80:73:80 | 1 | AccessorCalls.cs:73:78:73:81 | dynamic access to element | semmle.label | successor | -| ArrayCreation.cs:3:11:3:12 | enter M1 | ArrayCreation.cs:3:27:3:27 | 0 | semmle.label | successor | -| ArrayCreation.cs:3:11:3:12 | exit M1 (normal) | ArrayCreation.cs:3:11:3:12 | exit M1 | semmle.label | successor | -| ArrayCreation.cs:3:19:3:28 | array creation of type Int32[] | ArrayCreation.cs:3:11:3:12 | exit M1 (normal) | semmle.label | successor | -| ArrayCreation.cs:3:27:3:27 | 0 | ArrayCreation.cs:3:19:3:28 | array creation of type Int32[] | semmle.label | successor | -| ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:28:5:28 | 0 | semmle.label | successor | -| ArrayCreation.cs:5:12:5:13 | exit M2 (normal) | ArrayCreation.cs:5:12:5:13 | exit M2 | semmle.label | successor | -| ArrayCreation.cs:5:20:5:32 | array creation of type Int32[,] | ArrayCreation.cs:5:12:5:13 | exit M2 (normal) | semmle.label | successor | -| ArrayCreation.cs:5:28:5:28 | 0 | ArrayCreation.cs:5:31:5:31 | 1 | semmle.label | successor | -| ArrayCreation.cs:5:31:5:31 | 1 | ArrayCreation.cs:5:20:5:32 | array creation of type Int32[,] | semmle.label | successor | -| ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:19:7:36 | 2 | semmle.label | successor | -| ArrayCreation.cs:7:11:7:12 | exit M3 (normal) | ArrayCreation.cs:7:11:7:12 | exit M3 | semmle.label | successor | -| ArrayCreation.cs:7:19:7:36 | 2 | ArrayCreation.cs:7:19:7:36 | array creation of type Int32[] | semmle.label | successor | -| ArrayCreation.cs:7:19:7:36 | array creation of type Int32[] | ArrayCreation.cs:7:31:7:31 | 0 | semmle.label | successor | -| ArrayCreation.cs:7:29:7:36 | { ..., ... } | ArrayCreation.cs:7:11:7:12 | exit M3 (normal) | semmle.label | successor | -| ArrayCreation.cs:7:31:7:31 | 0 | ArrayCreation.cs:7:34:7:34 | 1 | semmle.label | successor | -| ArrayCreation.cs:7:34:7:34 | 1 | ArrayCreation.cs:7:29:7:36 | { ..., ... } | semmle.label | successor | -| ArrayCreation.cs:9:12:9:13 | enter M4 | ArrayCreation.cs:9:20:9:52 | 2 | semmle.label | successor | -| ArrayCreation.cs:9:12:9:13 | exit M4 (normal) | ArrayCreation.cs:9:12:9:13 | exit M4 | semmle.label | successor | -| ArrayCreation.cs:9:20:9:52 | 2 | ArrayCreation.cs:9:20:9:52 | 2 | semmle.label | successor | -| ArrayCreation.cs:9:20:9:52 | 2 | ArrayCreation.cs:9:20:9:52 | array creation of type Int32[,] | semmle.label | successor | -| ArrayCreation.cs:9:20:9:52 | array creation of type Int32[,] | ArrayCreation.cs:9:35:9:35 | 0 | semmle.label | successor | -| ArrayCreation.cs:9:31:9:52 | { ..., ... } | ArrayCreation.cs:9:12:9:13 | exit M4 (normal) | semmle.label | successor | -| ArrayCreation.cs:9:33:9:40 | { ..., ... } | ArrayCreation.cs:9:45:9:45 | 2 | semmle.label | successor | -| ArrayCreation.cs:9:35:9:35 | 0 | ArrayCreation.cs:9:38:9:38 | 1 | semmle.label | successor | -| ArrayCreation.cs:9:38:9:38 | 1 | ArrayCreation.cs:9:33:9:40 | { ..., ... } | semmle.label | successor | -| ArrayCreation.cs:9:43:9:50 | { ..., ... } | ArrayCreation.cs:9:31:9:52 | { ..., ... } | semmle.label | successor | -| ArrayCreation.cs:9:45:9:45 | 2 | ArrayCreation.cs:9:48:9:48 | 3 | semmle.label | successor | -| ArrayCreation.cs:9:48:9:48 | 3 | ArrayCreation.cs:9:43:9:50 | { ..., ... } | semmle.label | successor | -| Assert.cs:7:10:7:11 | enter M1 | Assert.cs:8:5:12:5 | {...} | semmle.label | successor | -| Assert.cs:7:10:7:11 | exit M1 (abnormal) | Assert.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| Assert.cs:7:10:7:11 | exit M1 (normal) | Assert.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| Assert.cs:8:5:12:5 | {...} | Assert.cs:9:9:9:33 | ... ...; | semmle.label | successor | -| Assert.cs:9:9:9:33 | ... ...; | Assert.cs:9:20:9:20 | access to parameter b | semmle.label | successor | -| Assert.cs:9:16:9:32 | String s = ... | Assert.cs:10:9:10:32 | ...; | semmle.label | successor | -| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:24:9:27 | null | semmle.label | true | -| Assert.cs:9:20:9:20 | access to parameter b | Assert.cs:9:31:9:32 | "" | semmle.label | false | -| Assert.cs:9:20:9:32 | ... ? ... : ... | Assert.cs:9:16:9:32 | String s = ... | semmle.label | successor | -| Assert.cs:9:24:9:27 | null | Assert.cs:9:20:9:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:9:31:9:32 | "" | Assert.cs:9:20:9:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | Assert.cs:7:10:7:11 | exit M1 (abnormal) | semmle.label | exit | -| Assert.cs:10:9:10:31 | [assertion success] call to method Assert | Assert.cs:11:9:11:36 | ...; | semmle.label | successor | -| Assert.cs:10:9:10:32 | ...; | Assert.cs:10:22:10:22 | access to local variable s | semmle.label | successor | -| Assert.cs:10:22:10:22 | access to local variable s | Assert.cs:10:27:10:30 | null | semmle.label | successor | -| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion failure] call to method Assert | semmle.label | false | -| Assert.cs:10:22:10:30 | ... != ... | Assert.cs:10:9:10:31 | [assertion success] call to method Assert | semmle.label | true | -| Assert.cs:10:27:10:30 | null | Assert.cs:10:22:10:30 | ... != ... | semmle.label | successor | -| Assert.cs:11:9:11:35 | call to method WriteLine | Assert.cs:7:10:7:11 | exit M1 (normal) | semmle.label | successor | -| Assert.cs:11:9:11:36 | ...; | Assert.cs:11:27:11:27 | access to local variable s | semmle.label | successor | -| Assert.cs:11:27:11:27 | access to local variable s | Assert.cs:11:27:11:34 | access to property Length | semmle.label | successor | -| Assert.cs:11:27:11:34 | access to property Length | Assert.cs:11:9:11:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:14:10:14:11 | enter M2 | Assert.cs:15:5:19:5 | {...} | semmle.label | successor | -| Assert.cs:14:10:14:11 | exit M2 (abnormal) | Assert.cs:14:10:14:11 | exit M2 | semmle.label | successor | -| Assert.cs:14:10:14:11 | exit M2 (normal) | Assert.cs:14:10:14:11 | exit M2 | semmle.label | successor | -| Assert.cs:15:5:19:5 | {...} | Assert.cs:16:9:16:33 | ... ...; | semmle.label | successor | -| Assert.cs:16:9:16:33 | ... ...; | Assert.cs:16:20:16:20 | access to parameter b | semmle.label | successor | -| Assert.cs:16:16:16:32 | String s = ... | Assert.cs:17:9:17:25 | ...; | semmle.label | successor | -| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:24:16:27 | null | semmle.label | true | -| Assert.cs:16:20:16:20 | access to parameter b | Assert.cs:16:31:16:32 | "" | semmle.label | false | -| Assert.cs:16:20:16:32 | ... ? ... : ... | Assert.cs:16:16:16:32 | String s = ... | semmle.label | successor | -| Assert.cs:16:24:16:27 | null | Assert.cs:16:20:16:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:16:31:16:32 | "" | Assert.cs:16:20:16:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | Assert.cs:14:10:14:11 | exit M2 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | Assert.cs:18:9:18:36 | ...; | semmle.label | successor | -| Assert.cs:17:9:17:25 | ...; | Assert.cs:17:23:17:23 | access to local variable s | semmle.label | successor | -| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion failure] call to method IsNull | semmle.label | non-null | -| Assert.cs:17:23:17:23 | access to local variable s | Assert.cs:17:9:17:24 | [assertion success] call to method IsNull | semmle.label | null | -| Assert.cs:18:9:18:35 | call to method WriteLine | Assert.cs:14:10:14:11 | exit M2 (normal) | semmle.label | successor | -| Assert.cs:18:9:18:36 | ...; | Assert.cs:18:27:18:27 | access to local variable s | semmle.label | successor | -| Assert.cs:18:27:18:27 | access to local variable s | Assert.cs:18:27:18:34 | access to property Length | semmle.label | successor | -| Assert.cs:18:27:18:34 | access to property Length | Assert.cs:18:9:18:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:21:10:21:11 | enter M3 | Assert.cs:22:5:26:5 | {...} | semmle.label | successor | -| Assert.cs:21:10:21:11 | exit M3 (abnormal) | Assert.cs:21:10:21:11 | exit M3 | semmle.label | successor | -| Assert.cs:21:10:21:11 | exit M3 (normal) | Assert.cs:21:10:21:11 | exit M3 | semmle.label | successor | -| Assert.cs:22:5:26:5 | {...} | Assert.cs:23:9:23:33 | ... ...; | semmle.label | successor | -| Assert.cs:23:9:23:33 | ... ...; | Assert.cs:23:20:23:20 | access to parameter b | semmle.label | successor | -| Assert.cs:23:16:23:32 | String s = ... | Assert.cs:24:9:24:28 | ...; | semmle.label | successor | -| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:24:23:27 | null | semmle.label | true | -| Assert.cs:23:20:23:20 | access to parameter b | Assert.cs:23:31:23:32 | "" | semmle.label | false | -| Assert.cs:23:20:23:32 | ... ? ... : ... | Assert.cs:23:16:23:32 | String s = ... | semmle.label | successor | -| Assert.cs:23:24:23:27 | null | Assert.cs:23:20:23:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:23:31:23:32 | "" | Assert.cs:23:20:23:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | Assert.cs:21:10:21:11 | exit M3 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | Assert.cs:25:9:25:36 | ...; | semmle.label | successor | -| Assert.cs:24:9:24:28 | ...; | Assert.cs:24:26:24:26 | access to local variable s | semmle.label | successor | -| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion failure] call to method IsNotNull | semmle.label | null | -| Assert.cs:24:26:24:26 | access to local variable s | Assert.cs:24:9:24:27 | [assertion success] call to method IsNotNull | semmle.label | non-null | -| Assert.cs:25:9:25:35 | call to method WriteLine | Assert.cs:21:10:21:11 | exit M3 (normal) | semmle.label | successor | -| Assert.cs:25:9:25:36 | ...; | Assert.cs:25:27:25:27 | access to local variable s | semmle.label | successor | -| Assert.cs:25:27:25:27 | access to local variable s | Assert.cs:25:27:25:34 | access to property Length | semmle.label | successor | -| Assert.cs:25:27:25:34 | access to property Length | Assert.cs:25:9:25:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:28:10:28:11 | enter M4 | Assert.cs:29:5:33:5 | {...} | semmle.label | successor | -| Assert.cs:28:10:28:11 | exit M4 (abnormal) | Assert.cs:28:10:28:11 | exit M4 | semmle.label | successor | -| Assert.cs:28:10:28:11 | exit M4 (normal) | Assert.cs:28:10:28:11 | exit M4 | semmle.label | successor | -| Assert.cs:29:5:33:5 | {...} | Assert.cs:30:9:30:33 | ... ...; | semmle.label | successor | -| Assert.cs:30:9:30:33 | ... ...; | Assert.cs:30:20:30:20 | access to parameter b | semmle.label | successor | -| Assert.cs:30:16:30:32 | String s = ... | Assert.cs:31:9:31:33 | ...; | semmle.label | successor | -| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:24:30:27 | null | semmle.label | true | -| Assert.cs:30:20:30:20 | access to parameter b | Assert.cs:30:31:30:32 | "" | semmle.label | false | -| Assert.cs:30:20:30:32 | ... ? ... : ... | Assert.cs:30:16:30:32 | String s = ... | semmle.label | successor | -| Assert.cs:30:24:30:27 | null | Assert.cs:30:20:30:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:30:31:30:32 | "" | Assert.cs:30:20:30:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | Assert.cs:28:10:28:11 | exit M4 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | Assert.cs:32:9:32:36 | ...; | semmle.label | successor | -| Assert.cs:31:9:31:33 | ...; | Assert.cs:31:23:31:23 | access to local variable s | semmle.label | successor | -| Assert.cs:31:23:31:23 | access to local variable s | Assert.cs:31:28:31:31 | null | semmle.label | successor | -| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion failure] call to method IsTrue | semmle.label | false | -| Assert.cs:31:23:31:31 | ... == ... | Assert.cs:31:9:31:32 | [assertion success] call to method IsTrue | semmle.label | true | -| Assert.cs:31:28:31:31 | null | Assert.cs:31:23:31:31 | ... == ... | semmle.label | successor | -| Assert.cs:32:9:32:35 | call to method WriteLine | Assert.cs:28:10:28:11 | exit M4 (normal) | semmle.label | successor | -| Assert.cs:32:9:32:36 | ...; | Assert.cs:32:27:32:27 | access to local variable s | semmle.label | successor | -| Assert.cs:32:27:32:27 | access to local variable s | Assert.cs:32:27:32:34 | access to property Length | semmle.label | successor | -| Assert.cs:32:27:32:34 | access to property Length | Assert.cs:32:9:32:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:35:10:35:11 | enter M5 | Assert.cs:36:5:40:5 | {...} | semmle.label | successor | -| Assert.cs:35:10:35:11 | exit M5 (abnormal) | Assert.cs:35:10:35:11 | exit M5 | semmle.label | successor | -| Assert.cs:35:10:35:11 | exit M5 (normal) | Assert.cs:35:10:35:11 | exit M5 | semmle.label | successor | -| Assert.cs:36:5:40:5 | {...} | Assert.cs:37:9:37:33 | ... ...; | semmle.label | successor | -| Assert.cs:37:9:37:33 | ... ...; | Assert.cs:37:20:37:20 | access to parameter b | semmle.label | successor | -| Assert.cs:37:16:37:32 | String s = ... | Assert.cs:38:9:38:33 | ...; | semmle.label | successor | -| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:24:37:27 | null | semmle.label | true | -| Assert.cs:37:20:37:20 | access to parameter b | Assert.cs:37:31:37:32 | "" | semmle.label | false | -| Assert.cs:37:20:37:32 | ... ? ... : ... | Assert.cs:37:16:37:32 | String s = ... | semmle.label | successor | -| Assert.cs:37:24:37:27 | null | Assert.cs:37:20:37:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:37:31:37:32 | "" | Assert.cs:37:20:37:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | Assert.cs:35:10:35:11 | exit M5 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | Assert.cs:39:9:39:36 | ...; | semmle.label | successor | -| Assert.cs:38:9:38:33 | ...; | Assert.cs:38:23:38:23 | access to local variable s | semmle.label | successor | -| Assert.cs:38:23:38:23 | access to local variable s | Assert.cs:38:28:38:31 | null | semmle.label | successor | -| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion failure] call to method IsTrue | semmle.label | false | -| Assert.cs:38:23:38:31 | ... != ... | Assert.cs:38:9:38:32 | [assertion success] call to method IsTrue | semmle.label | true | -| Assert.cs:38:28:38:31 | null | Assert.cs:38:23:38:31 | ... != ... | semmle.label | successor | -| Assert.cs:39:9:39:35 | call to method WriteLine | Assert.cs:35:10:35:11 | exit M5 (normal) | semmle.label | successor | -| Assert.cs:39:9:39:36 | ...; | Assert.cs:39:27:39:27 | access to local variable s | semmle.label | successor | -| Assert.cs:39:27:39:27 | access to local variable s | Assert.cs:39:27:39:34 | access to property Length | semmle.label | successor | -| Assert.cs:39:27:39:34 | access to property Length | Assert.cs:39:9:39:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:42:10:42:11 | enter M6 | Assert.cs:43:5:47:5 | {...} | semmle.label | successor | -| Assert.cs:42:10:42:11 | exit M6 (abnormal) | Assert.cs:42:10:42:11 | exit M6 | semmle.label | successor | -| Assert.cs:42:10:42:11 | exit M6 (normal) | Assert.cs:42:10:42:11 | exit M6 | semmle.label | successor | -| Assert.cs:43:5:47:5 | {...} | Assert.cs:44:9:44:33 | ... ...; | semmle.label | successor | -| Assert.cs:44:9:44:33 | ... ...; | Assert.cs:44:20:44:20 | access to parameter b | semmle.label | successor | -| Assert.cs:44:16:44:32 | String s = ... | Assert.cs:45:9:45:34 | ...; | semmle.label | successor | -| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:24:44:27 | null | semmle.label | true | -| Assert.cs:44:20:44:20 | access to parameter b | Assert.cs:44:31:44:32 | "" | semmle.label | false | -| Assert.cs:44:20:44:32 | ... ? ... : ... | Assert.cs:44:16:44:32 | String s = ... | semmle.label | successor | -| Assert.cs:44:24:44:27 | null | Assert.cs:44:20:44:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:44:31:44:32 | "" | Assert.cs:44:20:44:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | Assert.cs:42:10:42:11 | exit M6 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | Assert.cs:46:9:46:36 | ...; | semmle.label | successor | -| Assert.cs:45:9:45:34 | ...; | Assert.cs:45:24:45:24 | access to local variable s | semmle.label | successor | -| Assert.cs:45:24:45:24 | access to local variable s | Assert.cs:45:29:45:32 | null | semmle.label | successor | -| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion failure] call to method IsFalse | semmle.label | true | -| Assert.cs:45:24:45:32 | ... != ... | Assert.cs:45:9:45:33 | [assertion success] call to method IsFalse | semmle.label | false | -| Assert.cs:45:29:45:32 | null | Assert.cs:45:24:45:32 | ... != ... | semmle.label | successor | -| Assert.cs:46:9:46:35 | call to method WriteLine | Assert.cs:42:10:42:11 | exit M6 (normal) | semmle.label | successor | -| Assert.cs:46:9:46:36 | ...; | Assert.cs:46:27:46:27 | access to local variable s | semmle.label | successor | -| Assert.cs:46:27:46:27 | access to local variable s | Assert.cs:46:27:46:34 | access to property Length | semmle.label | successor | -| Assert.cs:46:27:46:34 | access to property Length | Assert.cs:46:9:46:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:49:10:49:11 | enter M7 | Assert.cs:50:5:54:5 | {...} | semmle.label | successor | -| Assert.cs:49:10:49:11 | exit M7 (abnormal) | Assert.cs:49:10:49:11 | exit M7 | semmle.label | successor | -| Assert.cs:49:10:49:11 | exit M7 (normal) | Assert.cs:49:10:49:11 | exit M7 | semmle.label | successor | -| Assert.cs:50:5:54:5 | {...} | Assert.cs:51:9:51:33 | ... ...; | semmle.label | successor | -| Assert.cs:51:9:51:33 | ... ...; | Assert.cs:51:20:51:20 | access to parameter b | semmle.label | successor | -| Assert.cs:51:16:51:32 | String s = ... | Assert.cs:52:9:52:34 | ...; | semmle.label | successor | -| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:24:51:27 | null | semmle.label | true | -| Assert.cs:51:20:51:20 | access to parameter b | Assert.cs:51:31:51:32 | "" | semmle.label | false | -| Assert.cs:51:20:51:32 | ... ? ... : ... | Assert.cs:51:16:51:32 | String s = ... | semmle.label | successor | -| Assert.cs:51:24:51:27 | null | Assert.cs:51:20:51:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:51:31:51:32 | "" | Assert.cs:51:20:51:32 | ... ? ... : ... | semmle.label | successor | -| Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | Assert.cs:49:10:49:11 | exit M7 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | Assert.cs:53:9:53:36 | ...; | semmle.label | successor | -| Assert.cs:52:9:52:34 | ...; | Assert.cs:52:24:52:24 | access to local variable s | semmle.label | successor | -| Assert.cs:52:24:52:24 | access to local variable s | Assert.cs:52:29:52:32 | null | semmle.label | successor | -| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion failure] call to method IsFalse | semmle.label | true | -| Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:9:52:33 | [assertion success] call to method IsFalse | semmle.label | false | -| Assert.cs:52:29:52:32 | null | Assert.cs:52:24:52:32 | ... == ... | semmle.label | successor | -| Assert.cs:53:9:53:35 | call to method WriteLine | Assert.cs:49:10:49:11 | exit M7 (normal) | semmle.label | successor | -| Assert.cs:53:9:53:36 | ...; | Assert.cs:53:27:53:27 | access to local variable s | semmle.label | successor | -| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:53:27:53:34 | access to property Length | semmle.label | successor | -| Assert.cs:53:27:53:34 | access to property Length | Assert.cs:53:9:53:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:56:10:56:11 | enter M8 | Assert.cs:57:5:61:5 | {...} | semmle.label | successor | -| Assert.cs:56:10:56:11 | exit M8 (abnormal) | Assert.cs:56:10:56:11 | exit M8 | semmle.label | successor | -| Assert.cs:56:10:56:11 | exit M8 (normal) | Assert.cs:56:10:56:11 | exit M8 | semmle.label | successor | -| Assert.cs:57:5:61:5 | {...} | Assert.cs:58:9:58:33 | ... ...; | semmle.label | successor | -| Assert.cs:58:9:58:33 | ... ...; | Assert.cs:58:20:58:20 | access to parameter b | semmle.label | successor | -| Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): false] ...; | semmle.label | successor | -| Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | Assert.cs:59:9:59:38 | [b (line 56): true] ...; | semmle.label | successor | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:24:58:27 | [b (line 56): true] null | semmle.label | true | -| Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:31:58:32 | [b (line 56): false] "" | semmle.label | false | -| Assert.cs:58:20:58:32 | [b (line 56): false] ... ? ... : ... | Assert.cs:58:16:58:32 | [b (line 56): false] String s = ... | semmle.label | successor | -| Assert.cs:58:20:58:32 | [b (line 56): true] ... ? ... : ... | Assert.cs:58:16:58:32 | [b (line 56): true] String s = ... | semmle.label | successor | -| Assert.cs:58:24:58:27 | [b (line 56): true] null | Assert.cs:58:20:58:32 | [b (line 56): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:58:31:58:32 | [b (line 56): false] "" | Assert.cs:58:20:58:32 | [b (line 56): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | Assert.cs:56:10:56:11 | exit M8 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | Assert.cs:60:9:60:36 | ...; | semmle.label | successor | -| Assert.cs:59:9:59:38 | [b (line 56): false] ...; | Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | semmle.label | successor | -| Assert.cs:59:9:59:38 | [b (line 56): true] ...; | Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | semmle.label | successor | -| Assert.cs:59:23:59:23 | [b (line 56): false] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): false] null | semmle.label | successor | -| Assert.cs:59:23:59:23 | [b (line 56): true] access to local variable s | Assert.cs:59:28:59:31 | [b (line 56): true] null | semmle.label | successor | -| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:23:59:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | semmle.label | true | -| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:23:59:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | semmle.label | true | -| Assert.cs:59:23:59:36 | [false] ... && ... | Assert.cs:59:9:59:37 | [assertion failure] call to method IsTrue | semmle.label | false | -| Assert.cs:59:23:59:36 | [true] ... && ... | Assert.cs:59:9:59:37 | [assertion success] call to method IsTrue | semmle.label | true | -| Assert.cs:59:28:59:31 | [b (line 56): false] null | Assert.cs:59:23:59:31 | [b (line 56): false] ... != ... | semmle.label | successor | -| Assert.cs:59:28:59:31 | [b (line 56): true] null | Assert.cs:59:23:59:31 | [b (line 56): true] ... != ... | semmle.label | successor | -| Assert.cs:59:36:59:36 | [b (line 56): false] access to parameter b | Assert.cs:59:23:59:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:59:36:59:36 | [b (line 56): true] access to parameter b | Assert.cs:59:23:59:36 | [true] ... && ... | semmle.label | true | -| Assert.cs:60:9:60:35 | call to method WriteLine | Assert.cs:56:10:56:11 | exit M8 (normal) | semmle.label | successor | -| Assert.cs:60:9:60:36 | ...; | Assert.cs:60:27:60:27 | access to local variable s | semmle.label | successor | -| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:60:27:60:34 | access to property Length | semmle.label | successor | -| Assert.cs:60:27:60:34 | access to property Length | Assert.cs:60:9:60:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:63:10:63:11 | enter M9 | Assert.cs:64:5:68:5 | {...} | semmle.label | successor | -| Assert.cs:63:10:63:11 | exit M9 (abnormal) | Assert.cs:63:10:63:11 | exit M9 | semmle.label | successor | -| Assert.cs:63:10:63:11 | exit M9 (normal) | Assert.cs:63:10:63:11 | exit M9 | semmle.label | successor | -| Assert.cs:64:5:68:5 | {...} | Assert.cs:65:9:65:33 | ... ...; | semmle.label | successor | -| Assert.cs:65:9:65:33 | ... ...; | Assert.cs:65:20:65:20 | access to parameter b | semmle.label | successor | -| Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): false] ...; | semmle.label | successor | -| Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | Assert.cs:66:9:66:39 | [b (line 63): true] ...; | semmle.label | successor | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:24:65:27 | [b (line 63): true] null | semmle.label | true | -| Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:31:65:32 | [b (line 63): false] "" | semmle.label | false | -| Assert.cs:65:20:65:32 | [b (line 63): false] ... ? ... : ... | Assert.cs:65:16:65:32 | [b (line 63): false] String s = ... | semmle.label | successor | -| Assert.cs:65:20:65:32 | [b (line 63): true] ... ? ... : ... | Assert.cs:65:16:65:32 | [b (line 63): true] String s = ... | semmle.label | successor | -| Assert.cs:65:24:65:27 | [b (line 63): true] null | Assert.cs:65:20:65:32 | [b (line 63): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:65:31:65:32 | [b (line 63): false] "" | Assert.cs:65:20:65:32 | [b (line 63): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | Assert.cs:63:10:63:11 | exit M9 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | Assert.cs:67:9:67:36 | ...; | semmle.label | successor | -| Assert.cs:66:9:66:39 | [b (line 63): false] ...; | Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | semmle.label | successor | -| Assert.cs:66:9:66:39 | [b (line 63): true] ...; | Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | semmle.label | successor | -| Assert.cs:66:24:66:24 | [b (line 63): false] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): false] null | semmle.label | successor | -| Assert.cs:66:24:66:24 | [b (line 63): true] access to local variable s | Assert.cs:66:29:66:32 | [b (line 63): true] null | semmle.label | successor | -| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:24:66:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | semmle.label | false | -| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:24:66:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | semmle.label | false | -| Assert.cs:66:24:66:37 | [false] ... \|\| ... | Assert.cs:66:9:66:38 | [assertion success] call to method IsFalse | semmle.label | false | -| Assert.cs:66:24:66:37 | [true] ... \|\| ... | Assert.cs:66:9:66:38 | [assertion failure] call to method IsFalse | semmle.label | true | -| Assert.cs:66:29:66:32 | [b (line 63): false] null | Assert.cs:66:24:66:32 | [b (line 63): false] ... == ... | semmle.label | successor | -| Assert.cs:66:29:66:32 | [b (line 63): true] null | Assert.cs:66:24:66:32 | [b (line 63): true] ... == ... | semmle.label | successor | -| Assert.cs:66:37:66:37 | [b (line 63): false] access to parameter b | Assert.cs:66:24:66:37 | [false] ... \|\| ... | semmle.label | false | -| Assert.cs:66:37:66:37 | [b (line 63): true] access to parameter b | Assert.cs:66:24:66:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:67:9:67:35 | call to method WriteLine | Assert.cs:63:10:63:11 | exit M9 (normal) | semmle.label | successor | -| Assert.cs:67:9:67:36 | ...; | Assert.cs:67:27:67:27 | access to local variable s | semmle.label | successor | -| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:67:27:67:34 | access to property Length | semmle.label | successor | -| Assert.cs:67:27:67:34 | access to property Length | Assert.cs:67:9:67:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:70:10:70:12 | enter M10 | Assert.cs:71:5:75:5 | {...} | semmle.label | successor | -| Assert.cs:70:10:70:12 | exit M10 (abnormal) | Assert.cs:70:10:70:12 | exit M10 | semmle.label | successor | -| Assert.cs:70:10:70:12 | exit M10 (normal) | Assert.cs:70:10:70:12 | exit M10 | semmle.label | successor | -| Assert.cs:71:5:75:5 | {...} | Assert.cs:72:9:72:33 | ... ...; | semmle.label | successor | -| Assert.cs:72:9:72:33 | ... ...; | Assert.cs:72:20:72:20 | access to parameter b | semmle.label | successor | -| Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): false] ...; | semmle.label | successor | -| Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | Assert.cs:73:9:73:38 | [b (line 70): true] ...; | semmle.label | successor | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:24:72:27 | [b (line 70): true] null | semmle.label | true | -| Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:31:72:32 | [b (line 70): false] "" | semmle.label | false | -| Assert.cs:72:20:72:32 | [b (line 70): false] ... ? ... : ... | Assert.cs:72:16:72:32 | [b (line 70): false] String s = ... | semmle.label | successor | -| Assert.cs:72:20:72:32 | [b (line 70): true] ... ? ... : ... | Assert.cs:72:16:72:32 | [b (line 70): true] String s = ... | semmle.label | successor | -| Assert.cs:72:24:72:27 | [b (line 70): true] null | Assert.cs:72:20:72:32 | [b (line 70): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:72:31:72:32 | [b (line 70): false] "" | Assert.cs:72:20:72:32 | [b (line 70): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | Assert.cs:70:10:70:12 | exit M10 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | Assert.cs:74:9:74:36 | ...; | semmle.label | successor | -| Assert.cs:73:9:73:38 | [b (line 70): false] ...; | Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | semmle.label | successor | -| Assert.cs:73:9:73:38 | [b (line 70): true] ...; | Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | semmle.label | successor | -| Assert.cs:73:23:73:23 | [b (line 70): false] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): false] null | semmle.label | successor | -| Assert.cs:73:23:73:23 | [b (line 70): true] access to local variable s | Assert.cs:73:28:73:31 | [b (line 70): true] null | semmle.label | successor | -| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:23:73:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | semmle.label | true | -| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:23:73:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | semmle.label | true | -| Assert.cs:73:23:73:36 | [false] ... && ... | Assert.cs:73:9:73:37 | [assertion failure] call to method IsTrue | semmle.label | false | -| Assert.cs:73:23:73:36 | [true] ... && ... | Assert.cs:73:9:73:37 | [assertion success] call to method IsTrue | semmle.label | true | -| Assert.cs:73:28:73:31 | [b (line 70): false] null | Assert.cs:73:23:73:31 | [b (line 70): false] ... == ... | semmle.label | successor | -| Assert.cs:73:28:73:31 | [b (line 70): true] null | Assert.cs:73:23:73:31 | [b (line 70): true] ... == ... | semmle.label | successor | -| Assert.cs:73:36:73:36 | [b (line 70): false] access to parameter b | Assert.cs:73:23:73:36 | [false] ... && ... | semmle.label | false | -| Assert.cs:73:36:73:36 | [b (line 70): true] access to parameter b | Assert.cs:73:23:73:36 | [true] ... && ... | semmle.label | true | -| Assert.cs:74:9:74:35 | call to method WriteLine | Assert.cs:70:10:70:12 | exit M10 (normal) | semmle.label | successor | -| Assert.cs:74:9:74:36 | ...; | Assert.cs:74:27:74:27 | access to local variable s | semmle.label | successor | -| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:74:27:74:34 | access to property Length | semmle.label | successor | -| Assert.cs:74:27:74:34 | access to property Length | Assert.cs:74:9:74:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:77:10:77:12 | enter M11 | Assert.cs:78:5:82:5 | {...} | semmle.label | successor | -| Assert.cs:77:10:77:12 | exit M11 (abnormal) | Assert.cs:77:10:77:12 | exit M11 | semmle.label | successor | -| Assert.cs:77:10:77:12 | exit M11 (normal) | Assert.cs:77:10:77:12 | exit M11 | semmle.label | successor | -| Assert.cs:78:5:82:5 | {...} | Assert.cs:79:9:79:33 | ... ...; | semmle.label | successor | -| Assert.cs:79:9:79:33 | ... ...; | Assert.cs:79:20:79:20 | access to parameter b | semmle.label | successor | -| Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): false] ...; | semmle.label | successor | -| Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | Assert.cs:80:9:80:39 | [b (line 77): true] ...; | semmle.label | successor | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:24:79:27 | [b (line 77): true] null | semmle.label | true | -| Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:31:79:32 | [b (line 77): false] "" | semmle.label | false | -| Assert.cs:79:20:79:32 | [b (line 77): false] ... ? ... : ... | Assert.cs:79:16:79:32 | [b (line 77): false] String s = ... | semmle.label | successor | -| Assert.cs:79:20:79:32 | [b (line 77): true] ... ? ... : ... | Assert.cs:79:16:79:32 | [b (line 77): true] String s = ... | semmle.label | successor | -| Assert.cs:79:24:79:27 | [b (line 77): true] null | Assert.cs:79:20:79:32 | [b (line 77): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:79:31:79:32 | [b (line 77): false] "" | Assert.cs:79:20:79:32 | [b (line 77): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | Assert.cs:77:10:77:12 | exit M11 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | Assert.cs:81:9:81:36 | ...; | semmle.label | successor | -| Assert.cs:80:9:80:39 | [b (line 77): false] ...; | Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | semmle.label | successor | -| Assert.cs:80:9:80:39 | [b (line 77): true] ...; | Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | semmle.label | successor | -| Assert.cs:80:24:80:24 | [b (line 77): false] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): false] null | semmle.label | successor | -| Assert.cs:80:24:80:24 | [b (line 77): true] access to local variable s | Assert.cs:80:29:80:32 | [b (line 77): true] null | semmle.label | successor | -| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:24:80:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | semmle.label | false | -| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:24:80:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | semmle.label | false | -| Assert.cs:80:24:80:37 | [false] ... \|\| ... | Assert.cs:80:9:80:38 | [assertion success] call to method IsFalse | semmle.label | false | -| Assert.cs:80:24:80:37 | [true] ... \|\| ... | Assert.cs:80:9:80:38 | [assertion failure] call to method IsFalse | semmle.label | true | -| Assert.cs:80:29:80:32 | [b (line 77): false] null | Assert.cs:80:24:80:32 | [b (line 77): false] ... != ... | semmle.label | successor | -| Assert.cs:80:29:80:32 | [b (line 77): true] null | Assert.cs:80:24:80:32 | [b (line 77): true] ... != ... | semmle.label | successor | -| Assert.cs:80:37:80:37 | [b (line 77): false] access to parameter b | Assert.cs:80:24:80:37 | [false] ... \|\| ... | semmle.label | false | -| Assert.cs:80:37:80:37 | [b (line 77): true] access to parameter b | Assert.cs:80:24:80:37 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:81:9:81:35 | call to method WriteLine | Assert.cs:77:10:77:12 | exit M11 (normal) | semmle.label | successor | -| Assert.cs:81:9:81:36 | ...; | Assert.cs:81:27:81:27 | access to local variable s | semmle.label | successor | -| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:81:27:81:34 | access to property Length | semmle.label | successor | -| Assert.cs:81:27:81:34 | access to property Length | Assert.cs:81:9:81:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:84:10:84:12 | enter M12 | Assert.cs:85:5:129:5 | {...} | semmle.label | successor | -| Assert.cs:84:10:84:12 | exit M12 (abnormal) | Assert.cs:84:10:84:12 | exit M12 | semmle.label | successor | -| Assert.cs:84:10:84:12 | exit M12 (normal) | Assert.cs:84:10:84:12 | exit M12 | semmle.label | successor | -| Assert.cs:85:5:129:5 | {...} | Assert.cs:86:9:86:33 | ... ...; | semmle.label | successor | -| Assert.cs:86:9:86:33 | ... ...; | Assert.cs:86:20:86:20 | access to parameter b | semmle.label | successor | -| Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | Assert.cs:87:9:87:32 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:24:86:27 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:86:20:86:20 | access to parameter b | Assert.cs:86:31:86:32 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:86:20:86:32 | [b (line 84): false] ... ? ... : ... | Assert.cs:86:16:86:32 | [b (line 84): false] String s = ... | semmle.label | successor | -| Assert.cs:86:20:86:32 | [b (line 84): true] ... ? ... : ... | Assert.cs:86:16:86:32 | [b (line 84): true] String s = ... | semmle.label | successor | -| Assert.cs:86:24:86:27 | [b (line 84): true] null | Assert.cs:86:20:86:32 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:86:31:86:32 | [b (line 84): false] "" | Assert.cs:86:20:86:32 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exit | -| Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exit | -| Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | Assert.cs:88:9:88:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:87:9:87:32 | [b (line 84): false] ...; | Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:87:9:87:32 | [b (line 84): true] ...; | Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:87:22:87:22 | [b (line 84): false] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:87:22:87:22 | [b (line 84): true] access to local variable s | Assert.cs:87:27:87:30 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): false] call to method Assert | semmle.label | false | -| Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): false] call to method Assert | semmle.label | true | -| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion failure, b (line 84): true] call to method Assert | semmle.label | false | -| Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | Assert.cs:87:9:87:31 | [assertion success, b (line 84): true] call to method Assert | semmle.label | true | -| Assert.cs:87:27:87:30 | [b (line 84): false] null | Assert.cs:87:22:87:30 | [b (line 84): false] ... != ... | semmle.label | successor | -| Assert.cs:87:27:87:30 | [b (line 84): true] null | Assert.cs:87:22:87:30 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | Assert.cs:90:9:90:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:88:9:88:36 | [b (line 84): false] ...; | Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:88:9:88:36 | [b (line 84): true] ...; | Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:88:27:88:27 | [b (line 84): false] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:88:27:88:27 | [b (line 84): true] access to local variable s | Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:88:27:88:34 | [b (line 84): false] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:88:27:88:34 | [b (line 84): true] access to property Length | Assert.cs:88:9:88:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | Assert.cs:91:9:91:25 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:90:9:90:26 | [b (line 84): false] ...; | Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:90:9:90:26 | [b (line 84): true] ...; | Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:90:13:90:13 | [b (line 84): false] access to parameter b | Assert.cs:90:24:90:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:90:13:90:13 | [b (line 84): true] access to parameter b | Assert.cs:90:17:90:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:90:9:90:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:90:9:90:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:90:17:90:20 | [b (line 84): true] null | Assert.cs:90:13:90:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:90:24:90:25 | [b (line 84): false] "" | Assert.cs:90:13:90:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | Assert.cs:92:9:92:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:91:9:91:25 | [b (line 84): false] ...; | Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:91:9:91:25 | [b (line 84): true] ...; | Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): false] call to method IsNull | semmle.label | non-null | -| Assert.cs:91:23:91:23 | [b (line 84): false] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): false] call to method IsNull | semmle.label | null | -| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion failure, b (line 84): true] call to method IsNull | semmle.label | non-null | -| Assert.cs:91:23:91:23 | [b (line 84): true] access to local variable s | Assert.cs:91:9:91:24 | [assertion success, b (line 84): true] call to method IsNull | semmle.label | null | -| Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | Assert.cs:94:9:94:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:92:9:92:36 | [b (line 84): false] ...; | Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:92:9:92:36 | [b (line 84): true] ...; | Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:92:27:92:27 | [b (line 84): false] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:92:27:92:27 | [b (line 84): true] access to local variable s | Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:92:27:92:34 | [b (line 84): false] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:92:27:92:34 | [b (line 84): true] access to property Length | Assert.cs:92:9:92:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | Assert.cs:95:9:95:28 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:94:9:94:26 | [b (line 84): false] ...; | Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:94:9:94:26 | [b (line 84): true] ...; | Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:94:13:94:13 | [b (line 84): false] access to parameter b | Assert.cs:94:24:94:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:94:13:94:13 | [b (line 84): true] access to parameter b | Assert.cs:94:17:94:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:94:9:94:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:94:9:94:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:94:17:94:20 | [b (line 84): true] null | Assert.cs:94:13:94:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:94:24:94:25 | [b (line 84): false] "" | Assert.cs:94:13:94:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | Assert.cs:96:9:96:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:95:9:95:28 | [b (line 84): false] ...; | Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:95:9:95:28 | [b (line 84): true] ...; | Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): false] call to method IsNotNull | semmle.label | null | -| Assert.cs:95:26:95:26 | [b (line 84): false] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): false] call to method IsNotNull | semmle.label | non-null | -| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion failure, b (line 84): true] call to method IsNotNull | semmle.label | null | -| Assert.cs:95:26:95:26 | [b (line 84): true] access to local variable s | Assert.cs:95:9:95:27 | [assertion success, b (line 84): true] call to method IsNotNull | semmle.label | non-null | -| Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | Assert.cs:98:9:98:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:96:9:96:36 | [b (line 84): false] ...; | Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:96:9:96:36 | [b (line 84): true] ...; | Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:96:27:96:27 | [b (line 84): false] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:96:27:96:27 | [b (line 84): true] access to local variable s | Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:96:27:96:34 | [b (line 84): false] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:96:27:96:34 | [b (line 84): true] access to property Length | Assert.cs:96:9:96:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | Assert.cs:99:9:99:33 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:98:9:98:26 | [b (line 84): false] ...; | Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:98:9:98:26 | [b (line 84): true] ...; | Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:98:13:98:13 | [b (line 84): false] access to parameter b | Assert.cs:98:24:98:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:98:13:98:13 | [b (line 84): true] access to parameter b | Assert.cs:98:17:98:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:98:9:98:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:98:9:98:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:98:17:98:20 | [b (line 84): true] null | Assert.cs:98:13:98:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:98:24:98:25 | [b (line 84): false] "" | Assert.cs:98:13:98:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:100:9:100:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:99:9:99:33 | [b (line 84): false] ...; | Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:99:9:99:33 | [b (line 84): true] ...; | Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:99:23:99:23 | [b (line 84): false] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:99:23:99:23 | [b (line 84): true] access to local variable s | Assert.cs:99:28:99:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | -| Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): false] call to method IsTrue | semmle.label | true | -| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | -| Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | Assert.cs:99:9:99:32 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | -| Assert.cs:99:28:99:31 | [b (line 84): false] null | Assert.cs:99:23:99:31 | [b (line 84): false] ... == ... | semmle.label | successor | -| Assert.cs:99:28:99:31 | [b (line 84): true] null | Assert.cs:99:23:99:31 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | Assert.cs:102:9:102:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:100:9:100:36 | [b (line 84): false] ...; | Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:100:9:100:36 | [b (line 84): true] ...; | Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:100:27:100:27 | [b (line 84): false] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:100:27:100:27 | [b (line 84): true] access to local variable s | Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:100:27:100:34 | [b (line 84): false] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:100:27:100:34 | [b (line 84): true] access to property Length | Assert.cs:100:9:100:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | Assert.cs:103:9:103:33 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:102:9:102:26 | [b (line 84): false] ...; | Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:102:9:102:26 | [b (line 84): true] ...; | Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:102:13:102:13 | [b (line 84): false] access to parameter b | Assert.cs:102:24:102:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:102:13:102:13 | [b (line 84): true] access to parameter b | Assert.cs:102:17:102:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:102:9:102:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:102:9:102:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:102:17:102:20 | [b (line 84): true] null | Assert.cs:102:13:102:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:102:24:102:25 | [b (line 84): false] "" | Assert.cs:102:13:102:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:104:9:104:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:103:9:103:33 | [b (line 84): false] ...; | Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:103:9:103:33 | [b (line 84): true] ...; | Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:103:23:103:23 | [b (line 84): false] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:103:23:103:23 | [b (line 84): true] access to local variable s | Assert.cs:103:28:103:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | -| Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): false] call to method IsTrue | semmle.label | true | -| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | -| Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | Assert.cs:103:9:103:32 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | -| Assert.cs:103:28:103:31 | [b (line 84): false] null | Assert.cs:103:23:103:31 | [b (line 84): false] ... != ... | semmle.label | successor | -| Assert.cs:103:28:103:31 | [b (line 84): true] null | Assert.cs:103:23:103:31 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | Assert.cs:106:9:106:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:104:9:104:36 | [b (line 84): false] ...; | Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:104:9:104:36 | [b (line 84): true] ...; | Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:104:27:104:27 | [b (line 84): false] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:104:27:104:27 | [b (line 84): true] access to local variable s | Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:104:27:104:34 | [b (line 84): false] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:104:27:104:34 | [b (line 84): true] access to property Length | Assert.cs:104:9:104:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | Assert.cs:107:9:107:34 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:106:9:106:26 | [b (line 84): false] ...; | Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:106:9:106:26 | [b (line 84): true] ...; | Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:106:13:106:13 | [b (line 84): false] access to parameter b | Assert.cs:106:24:106:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:106:13:106:13 | [b (line 84): true] access to parameter b | Assert.cs:106:17:106:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:106:9:106:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:106:9:106:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:106:17:106:20 | [b (line 84): true] null | Assert.cs:106:13:106:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:106:24:106:25 | [b (line 84): false] "" | Assert.cs:106:13:106:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:108:9:108:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:107:9:107:34 | [b (line 84): false] ...; | Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:107:9:107:34 | [b (line 84): true] ...; | Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:107:24:107:24 | [b (line 84): false] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:107:24:107:24 | [b (line 84): true] access to local variable s | Assert.cs:107:29:107:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): false] call to method IsFalse | semmle.label | true | -| Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): false] call to method IsFalse | semmle.label | false | -| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | -| Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | Assert.cs:107:9:107:33 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | false | -| Assert.cs:107:29:107:32 | [b (line 84): false] null | Assert.cs:107:24:107:32 | [b (line 84): false] ... != ... | semmle.label | successor | -| Assert.cs:107:29:107:32 | [b (line 84): true] null | Assert.cs:107:24:107:32 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | Assert.cs:110:9:110:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:108:9:108:36 | [b (line 84): false] ...; | Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:108:9:108:36 | [b (line 84): true] ...; | Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:108:27:108:27 | [b (line 84): false] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:108:27:108:27 | [b (line 84): true] access to local variable s | Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:108:27:108:34 | [b (line 84): false] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:108:27:108:34 | [b (line 84): true] access to property Length | Assert.cs:108:9:108:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | Assert.cs:111:9:111:34 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:110:9:110:26 | [b (line 84): false] ...; | Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:110:9:110:26 | [b (line 84): true] ...; | Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:110:13:110:13 | [b (line 84): false] access to parameter b | Assert.cs:110:24:110:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:110:13:110:13 | [b (line 84): true] access to parameter b | Assert.cs:110:17:110:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:110:9:110:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:110:9:110:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:110:17:110:20 | [b (line 84): true] null | Assert.cs:110:13:110:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:110:24:110:25 | [b (line 84): false] "" | Assert.cs:110:13:110:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:112:9:112:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:111:9:111:34 | [b (line 84): false] ...; | Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:111:9:111:34 | [b (line 84): true] ...; | Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:111:24:111:24 | [b (line 84): false] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:111:24:111:24 | [b (line 84): true] access to local variable s | Assert.cs:111:29:111:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): false] call to method IsFalse | semmle.label | true | -| Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): false] call to method IsFalse | semmle.label | false | -| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | -| Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | Assert.cs:111:9:111:33 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | false | -| Assert.cs:111:29:111:32 | [b (line 84): false] null | Assert.cs:111:24:111:32 | [b (line 84): false] ... == ... | semmle.label | successor | -| Assert.cs:111:29:111:32 | [b (line 84): true] null | Assert.cs:111:24:111:32 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | Assert.cs:114:9:114:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:112:9:112:36 | [b (line 84): false] ...; | Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:112:9:112:36 | [b (line 84): true] ...; | Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:112:27:112:27 | [b (line 84): false] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | semmle.label | successor | -| Assert.cs:112:27:112:27 | [b (line 84): true] access to local variable s | Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:112:27:112:34 | [b (line 84): false] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): false] call to method WriteLine | semmle.label | successor | -| Assert.cs:112:27:112:34 | [b (line 84): true] access to property Length | Assert.cs:112:9:112:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): false] ...; | semmle.label | successor | -| Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | Assert.cs:115:9:115:38 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:114:9:114:26 | [b (line 84): false] ...; | Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | semmle.label | successor | -| Assert.cs:114:9:114:26 | [b (line 84): true] ...; | Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:114:13:114:13 | [b (line 84): false] access to parameter b | Assert.cs:114:24:114:25 | [b (line 84): false] "" | semmle.label | false | -| Assert.cs:114:13:114:13 | [b (line 84): true] access to parameter b | Assert.cs:114:17:114:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | Assert.cs:114:9:114:25 | [b (line 84): false] ... = ... | semmle.label | successor | -| Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:114:9:114:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:114:17:114:20 | [b (line 84): true] null | Assert.cs:114:13:114:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:114:24:114:25 | [b (line 84): false] "" | Assert.cs:114:13:114:25 | [b (line 84): false] ... ? ... : ... | semmle.label | successor | -| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:116:9:116:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:115:9:115:38 | [b (line 84): false] ...; | Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | semmle.label | successor | -| Assert.cs:115:9:115:38 | [b (line 84): true] ...; | Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:115:23:115:23 | [b (line 84): false] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): false] null | semmle.label | successor | -| Assert.cs:115:23:115:23 | [b (line 84): true] access to local variable s | Assert.cs:115:28:115:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:23:115:36 | [false, b (line 84): false] ... && ... | semmle.label | false | -| Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | semmle.label | true | -| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:23:115:36 | [false, b (line 84): true] ... && ... | semmle.label | false | -| Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | semmle.label | true | -| Assert.cs:115:23:115:36 | [false, b (line 84): false] ... && ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): false] call to method IsTrue | semmle.label | false | -| Assert.cs:115:23:115:36 | [false, b (line 84): true] ... && ... | Assert.cs:115:9:115:37 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | -| Assert.cs:115:23:115:36 | [true, b (line 84): true] ... && ... | Assert.cs:115:9:115:37 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | -| Assert.cs:115:28:115:31 | [b (line 84): false] null | Assert.cs:115:23:115:31 | [b (line 84): false] ... != ... | semmle.label | successor | -| Assert.cs:115:28:115:31 | [b (line 84): true] null | Assert.cs:115:23:115:31 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:115:36:115:36 | [b (line 84): false] access to parameter b | Assert.cs:115:23:115:36 | [false, b (line 84): false] ... && ... | semmle.label | false | -| Assert.cs:115:36:115:36 | [b (line 84): true] access to parameter b | Assert.cs:115:23:115:36 | [true, b (line 84): true] ... && ... | semmle.label | true | -| Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | Assert.cs:118:9:118:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:116:9:116:36 | [b (line 84): true] ...; | Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:116:27:116:27 | [b (line 84): true] access to local variable s | Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:116:27:116:34 | [b (line 84): true] access to property Length | Assert.cs:116:9:116:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | Assert.cs:119:9:119:40 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:118:9:118:26 | [b (line 84): true] ...; | Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:118:13:118:13 | [b (line 84): true] access to parameter b | Assert.cs:118:17:118:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:118:9:118:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:118:17:118:20 | [b (line 84): true] null | Assert.cs:118:13:118:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | Assert.cs:120:9:120:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:119:9:119:40 | [b (line 84): true] ...; | Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:119:24:119:24 | [b (line 84): true] access to local variable s | Assert.cs:119:29:119:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:24:119:38 | [true, b (line 84): true] ... \|\| ... | semmle.label | true | -| Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | semmle.label | false | -| Assert.cs:119:24:119:38 | [false, b (line 84): true] ... \|\| ... | Assert.cs:119:9:119:39 | [assertion success, b (line 84): true] call to method IsFalse | semmle.label | false | -| Assert.cs:119:24:119:38 | [true, b (line 84): true] ... \|\| ... | Assert.cs:119:9:119:39 | [assertion failure, b (line 84): true] call to method IsFalse | semmle.label | true | -| Assert.cs:119:29:119:32 | [b (line 84): true] null | Assert.cs:119:24:119:32 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:119:37:119:38 | [false, b (line 84): true] !... | Assert.cs:119:24:119:38 | [false, b (line 84): true] ... \|\| ... | semmle.label | false | -| Assert.cs:119:38:119:38 | [b (line 84): true] access to parameter b | Assert.cs:119:37:119:38 | [false, b (line 84): true] !... | semmle.label | true | -| Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | Assert.cs:122:9:122:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:120:9:120:36 | [b (line 84): true] ...; | Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:120:27:120:27 | [b (line 84): true] access to local variable s | Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:120:27:120:34 | [b (line 84): true] access to property Length | Assert.cs:120:9:120:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | Assert.cs:123:9:123:38 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:122:9:122:26 | [b (line 84): true] ...; | Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:122:13:122:13 | [b (line 84): true] access to parameter b | Assert.cs:122:17:122:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:122:9:122:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:122:17:122:20 | [b (line 84): true] null | Assert.cs:122:13:122:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | Assert.cs:124:9:124:36 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:123:9:123:38 | [b (line 84): true] ...; | Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:123:23:123:23 | [b (line 84): true] access to local variable s | Assert.cs:123:28:123:31 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:23:123:36 | [false, b (line 84): true] ... && ... | semmle.label | false | -| Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | semmle.label | true | -| Assert.cs:123:23:123:36 | [false, b (line 84): true] ... && ... | Assert.cs:123:9:123:37 | [assertion failure, b (line 84): true] call to method IsTrue | semmle.label | false | -| Assert.cs:123:23:123:36 | [true, b (line 84): true] ... && ... | Assert.cs:123:9:123:37 | [assertion success, b (line 84): true] call to method IsTrue | semmle.label | true | -| Assert.cs:123:28:123:31 | [b (line 84): true] null | Assert.cs:123:23:123:31 | [b (line 84): true] ... == ... | semmle.label | successor | -| Assert.cs:123:36:123:36 | [b (line 84): true] access to parameter b | Assert.cs:123:23:123:36 | [true, b (line 84): true] ... && ... | semmle.label | true | -| Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | Assert.cs:126:9:126:26 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:124:9:124:36 | [b (line 84): true] ...; | Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:124:27:124:27 | [b (line 84): true] access to local variable s | Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | semmle.label | successor | -| Assert.cs:124:27:124:34 | [b (line 84): true] access to property Length | Assert.cs:124:9:124:35 | [b (line 84): true] call to method WriteLine | semmle.label | successor | -| Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | Assert.cs:127:9:127:40 | [b (line 84): true] ...; | semmle.label | successor | -| Assert.cs:126:9:126:26 | [b (line 84): true] ...; | Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | semmle.label | successor | -| Assert.cs:126:13:126:13 | [b (line 84): true] access to parameter b | Assert.cs:126:17:126:20 | [b (line 84): true] null | semmle.label | true | -| Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | Assert.cs:126:9:126:25 | [b (line 84): true] ... = ... | semmle.label | successor | -| Assert.cs:126:17:126:20 | [b (line 84): true] null | Assert.cs:126:13:126:25 | [b (line 84): true] ... ? ... : ... | semmle.label | successor | -| Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | Assert.cs:84:10:84:12 | exit M12 (abnormal) | semmle.label | exception(AssertFailedException) | -| Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | Assert.cs:128:9:128:36 | ...; | semmle.label | successor | -| Assert.cs:127:9:127:40 | [b (line 84): true] ...; | Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | semmle.label | successor | -| Assert.cs:127:24:127:24 | [b (line 84): true] access to local variable s | Assert.cs:127:29:127:32 | [b (line 84): true] null | semmle.label | successor | -| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:24:127:38 | [true] ... \|\| ... | semmle.label | true | -| Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | semmle.label | false | -| Assert.cs:127:24:127:38 | [false] ... \|\| ... | Assert.cs:127:9:127:39 | [assertion success] call to method IsFalse | semmle.label | false | -| Assert.cs:127:24:127:38 | [true] ... \|\| ... | Assert.cs:127:9:127:39 | [assertion failure] call to method IsFalse | semmle.label | true | -| Assert.cs:127:29:127:32 | [b (line 84): true] null | Assert.cs:127:24:127:32 | [b (line 84): true] ... != ... | semmle.label | successor | -| Assert.cs:127:37:127:38 | [false] !... | Assert.cs:127:24:127:38 | [false] ... \|\| ... | semmle.label | false | -| Assert.cs:127:38:127:38 | [b (line 84): true] access to parameter b | Assert.cs:127:37:127:38 | [false] !... | semmle.label | true | -| Assert.cs:128:9:128:35 | call to method WriteLine | Assert.cs:84:10:84:12 | exit M12 (normal) | semmle.label | successor | -| Assert.cs:128:9:128:36 | ...; | Assert.cs:128:27:128:27 | access to local variable s | semmle.label | successor | -| Assert.cs:128:27:128:27 | access to local variable s | Assert.cs:128:27:128:34 | access to property Length | semmle.label | successor | -| Assert.cs:128:27:128:34 | access to property Length | Assert.cs:128:9:128:35 | call to method WriteLine | semmle.label | successor | -| Assert.cs:131:18:131:32 | enter AssertTrueFalse | Assert.cs:135:5:136:5 | {...} | semmle.label | successor | -| Assert.cs:131:18:131:32 | exit AssertTrueFalse (normal) | Assert.cs:131:18:131:32 | exit AssertTrueFalse | semmle.label | successor | -| Assert.cs:135:5:136:5 | {...} | Assert.cs:131:18:131:32 | exit AssertTrueFalse (normal) | semmle.label | successor | -| Assert.cs:138:10:138:12 | enter M13 | Assert.cs:139:5:142:5 | {...} | semmle.label | successor | -| Assert.cs:138:10:138:12 | exit M13 (abnormal) | Assert.cs:138:10:138:12 | exit M13 | semmle.label | successor | -| Assert.cs:138:10:138:12 | exit M13 (normal) | Assert.cs:138:10:138:12 | exit M13 | semmle.label | successor | -| Assert.cs:139:5:142:5 | {...} | Assert.cs:140:9:140:36 | ...; | semmle.label | successor | -| Assert.cs:140:9:140:35 | [assertion failure] call to method AssertTrueFalse | Assert.cs:138:10:138:12 | exit M13 (abnormal) | semmle.label | exception(Exception) | -| Assert.cs:140:9:140:35 | [assertion failure] call to method AssertTrueFalse | Assert.cs:138:10:138:12 | exit M13 (abnormal) | semmle.label | exception(Exception) | -| Assert.cs:140:9:140:35 | [assertion success] call to method AssertTrueFalse | Assert.cs:141:9:141:15 | return ...; | semmle.label | successor | -| Assert.cs:140:9:140:35 | this access | Assert.cs:140:25:140:26 | access to parameter b1 | semmle.label | successor | -| Assert.cs:140:9:140:36 | ...; | Assert.cs:140:9:140:35 | this access | semmle.label | successor | -| Assert.cs:140:25:140:26 | access to parameter b1 | Assert.cs:140:29:140:30 | [assertion failure] access to parameter b2 | semmle.label | false | -| Assert.cs:140:25:140:26 | access to parameter b1 | Assert.cs:140:29:140:30 | access to parameter b2 | semmle.label | true | -| Assert.cs:140:29:140:30 | [assertion failure] access to parameter b2 | Assert.cs:140:33:140:34 | [assertion failure] access to parameter b3 | semmle.label | false | -| Assert.cs:140:29:140:30 | [assertion failure] access to parameter b2 | Assert.cs:140:33:140:34 | [assertion failure] access to parameter b3 | semmle.label | true | -| Assert.cs:140:29:140:30 | access to parameter b2 | Assert.cs:140:33:140:34 | [assertion failure] access to parameter b3 | semmle.label | true | -| Assert.cs:140:29:140:30 | access to parameter b2 | Assert.cs:140:33:140:34 | [assertion success] access to parameter b3 | semmle.label | false | -| Assert.cs:140:33:140:34 | [assertion failure] access to parameter b3 | Assert.cs:140:9:140:35 | [assertion failure] call to method AssertTrueFalse | semmle.label | successor | -| Assert.cs:140:33:140:34 | [assertion failure] access to parameter b3 | Assert.cs:140:9:140:35 | [assertion failure] call to method AssertTrueFalse | semmle.label | successor | -| Assert.cs:140:33:140:34 | [assertion success] access to parameter b3 | Assert.cs:140:9:140:35 | [assertion success] call to method AssertTrueFalse | semmle.label | successor | -| Assert.cs:141:9:141:15 | return ...; | Assert.cs:138:10:138:12 | exit M13 (normal) | semmle.label | return | -| Assignments.cs:3:10:3:10 | enter M | Assignments.cs:4:5:15:5 | {...} | semmle.label | successor | -| Assignments.cs:3:10:3:10 | exit M (normal) | Assignments.cs:3:10:3:10 | exit M | semmle.label | successor | -| Assignments.cs:4:5:15:5 | {...} | Assignments.cs:5:9:5:18 | ... ...; | semmle.label | successor | -| Assignments.cs:5:9:5:18 | ... ...; | Assignments.cs:5:17:5:17 | 0 | semmle.label | successor | -| Assignments.cs:5:13:5:17 | Int32 x = ... | Assignments.cs:6:9:6:15 | ...; | semmle.label | successor | -| Assignments.cs:5:17:5:17 | 0 | Assignments.cs:5:13:5:17 | Int32 x = ... | semmle.label | successor | -| Assignments.cs:6:9:6:9 | access to local variable x | Assignments.cs:6:14:6:14 | 1 | semmle.label | successor | -| Assignments.cs:6:9:6:14 | ... + ... | Assignments.cs:6:9:6:14 | ... = ... | semmle.label | successor | -| Assignments.cs:6:9:6:14 | ... = ... | Assignments.cs:8:9:8:22 | ... ...; | semmle.label | successor | -| Assignments.cs:6:9:6:15 | ...; | Assignments.cs:6:9:6:9 | access to local variable x | semmle.label | successor | -| Assignments.cs:6:14:6:14 | 1 | Assignments.cs:6:9:6:14 | ... + ... | semmle.label | successor | -| Assignments.cs:8:9:8:22 | ... ...; | Assignments.cs:8:21:8:21 | 0 | semmle.label | successor | -| Assignments.cs:8:17:8:21 | dynamic d = ... | Assignments.cs:9:9:9:15 | ...; | semmle.label | successor | -| Assignments.cs:8:21:8:21 | 0 | Assignments.cs:8:21:8:21 | (...) ... | semmle.label | successor | -| Assignments.cs:8:21:8:21 | (...) ... | Assignments.cs:8:17:8:21 | dynamic d = ... | semmle.label | successor | -| Assignments.cs:9:9:9:9 | access to local variable d | Assignments.cs:9:14:9:14 | 2 | semmle.label | successor | -| Assignments.cs:9:9:9:14 | ... = ... | Assignments.cs:11:9:11:34 | ... ...; | semmle.label | successor | -| Assignments.cs:9:9:9:14 | dynamic call to operator - | Assignments.cs:9:9:9:14 | ... = ... | semmle.label | successor | -| Assignments.cs:9:9:9:15 | ...; | Assignments.cs:9:9:9:9 | access to local variable d | semmle.label | successor | -| Assignments.cs:9:14:9:14 | 2 | Assignments.cs:9:9:9:14 | dynamic call to operator - | semmle.label | successor | -| Assignments.cs:11:9:11:34 | ... ...; | Assignments.cs:11:17:11:33 | object creation of type Assignments | semmle.label | successor | -| Assignments.cs:11:13:11:33 | Assignments a = ... | Assignments.cs:12:9:12:18 | ...; | semmle.label | successor | -| Assignments.cs:11:17:11:33 | object creation of type Assignments | Assignments.cs:11:13:11:33 | Assignments a = ... | semmle.label | successor | -| Assignments.cs:12:9:12:9 | access to local variable a | Assignments.cs:12:14:12:17 | this access | semmle.label | successor | -| Assignments.cs:12:9:12:17 | ... = ... | Assignments.cs:14:9:14:36 | ...; | semmle.label | successor | -| Assignments.cs:12:9:12:17 | call to operator + | Assignments.cs:12:9:12:17 | ... = ... | semmle.label | successor | -| Assignments.cs:12:9:12:18 | ...; | Assignments.cs:12:9:12:9 | access to local variable a | semmle.label | successor | -| Assignments.cs:12:14:12:17 | this access | Assignments.cs:12:9:12:17 | call to operator + | semmle.label | successor | -| Assignments.cs:14:9:14:13 | access to event Event | Assignments.cs:14:9:14:35 | ... += ... | semmle.label | successor | -| Assignments.cs:14:9:14:13 | this access | Assignments.cs:14:18:14:35 | (...) => ... | semmle.label | successor | -| Assignments.cs:14:9:14:35 | ... += ... | Assignments.cs:3:10:3:10 | exit M (normal) | semmle.label | successor | -| Assignments.cs:14:9:14:36 | ...; | Assignments.cs:14:9:14:13 | this access | semmle.label | successor | -| Assignments.cs:14:18:14:35 | (...) => ... | Assignments.cs:14:9:14:13 | access to event Event | semmle.label | successor | -| Assignments.cs:14:18:14:35 | enter (...) => ... | Assignments.cs:14:33:14:35 | {...} | semmle.label | successor | -| Assignments.cs:14:18:14:35 | exit (...) => ... (normal) | Assignments.cs:14:18:14:35 | exit (...) => ... | semmle.label | successor | -| Assignments.cs:14:33:14:35 | {...} | Assignments.cs:14:18:14:35 | exit (...) => ... (normal) | semmle.label | successor | -| Assignments.cs:17:40:17:40 | enter + | Assignments.cs:18:5:20:5 | {...} | semmle.label | successor | -| Assignments.cs:17:40:17:40 | exit + (normal) | Assignments.cs:17:40:17:40 | exit + | semmle.label | successor | -| Assignments.cs:18:5:20:5 | {...} | Assignments.cs:19:16:19:16 | access to parameter x | semmle.label | successor | -| Assignments.cs:19:9:19:17 | return ...; | Assignments.cs:17:40:17:40 | exit + (normal) | semmle.label | return | -| Assignments.cs:19:16:19:16 | access to parameter x | Assignments.cs:19:9:19:17 | return ...; | semmle.label | successor | -| BreakInTry.cs:3:10:3:11 | enter M1 | BreakInTry.cs:4:5:18:5 | {...} | semmle.label | successor | -| BreakInTry.cs:3:10:3:11 | exit M1 (normal) | BreakInTry.cs:3:10:3:11 | exit M1 | semmle.label | successor | -| BreakInTry.cs:4:5:18:5 | {...} | BreakInTry.cs:5:9:17:9 | try {...} ... | semmle.label | successor | -| BreakInTry.cs:5:9:17:9 | try {...} ... | BreakInTry.cs:6:9:12:9 | {...} | semmle.label | successor | -| BreakInTry.cs:6:9:12:9 | {...} | BreakInTry.cs:7:33:7:36 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:7:26:7:28 | String arg | semmle.label | non-empty | -| BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | BreakInTry.cs:14:9:17:9 | {...} | semmle.label | empty | -| BreakInTry.cs:7:26:7:28 | String arg | BreakInTry.cs:8:13:11:13 | {...} | semmle.label | successor | -| BreakInTry.cs:7:33:7:36 | access to parameter args | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:8:13:11:13 | {...} | BreakInTry.cs:9:17:10:26 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:9:17:10:26 | if (...) ... | BreakInTry.cs:9:21:9:23 | access to local variable arg | semmle.label | successor | -| BreakInTry.cs:9:21:9:23 | access to local variable arg | BreakInTry.cs:9:28:9:31 | null | semmle.label | successor | -| BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:7:13:11:13 | foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:9:21:9:31 | ... == ... | BreakInTry.cs:10:21:10:26 | break; | semmle.label | true | -| BreakInTry.cs:9:28:9:31 | null | BreakInTry.cs:9:21:9:31 | ... == ... | semmle.label | successor | -| BreakInTry.cs:10:21:10:26 | break; | BreakInTry.cs:14:9:17:9 | {...} | semmle.label | break | -| BreakInTry.cs:14:9:17:9 | {...} | BreakInTry.cs:15:13:16:17 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:15:13:16:17 | if (...) ... | BreakInTry.cs:15:17:15:20 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:15:17:15:20 | access to parameter args | BreakInTry.cs:15:25:15:28 | null | semmle.label | successor | -| BreakInTry.cs:15:17:15:28 | ... == ... | BreakInTry.cs:3:10:3:11 | exit M1 (normal) | semmle.label | false | -| BreakInTry.cs:15:17:15:28 | ... == ... | BreakInTry.cs:16:17:16:17 | ; | semmle.label | true | -| BreakInTry.cs:15:25:15:28 | null | BreakInTry.cs:15:17:15:28 | ... == ... | semmle.label | successor | -| BreakInTry.cs:16:17:16:17 | ; | BreakInTry.cs:3:10:3:11 | exit M1 (normal) | semmle.label | successor | -| BreakInTry.cs:20:10:20:11 | enter M2 | BreakInTry.cs:21:5:36:5 | {...} | semmle.label | successor | -| BreakInTry.cs:20:10:20:11 | exit M2 (normal) | BreakInTry.cs:20:10:20:11 | exit M2 | semmle.label | successor | -| BreakInTry.cs:21:5:36:5 | {...} | BreakInTry.cs:22:29:22:32 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:22:22:22:24 | String arg | semmle.label | non-empty | -| BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | BreakInTry.cs:35:7:35:7 | ; | semmle.label | empty | -| BreakInTry.cs:22:22:22:24 | String arg | BreakInTry.cs:23:9:34:9 | {...} | semmle.label | successor | -| BreakInTry.cs:22:29:22:32 | access to parameter args | BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:23:9:34:9 | {...} | BreakInTry.cs:24:13:33:13 | try {...} ... | semmle.label | successor | -| BreakInTry.cs:24:13:33:13 | try {...} ... | BreakInTry.cs:25:13:28:13 | {...} | semmle.label | successor | -| BreakInTry.cs:25:13:28:13 | {...} | BreakInTry.cs:26:17:27:26 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:26:17:27:26 | if (...) ... | BreakInTry.cs:26:21:26:23 | access to local variable arg | semmle.label | successor | -| BreakInTry.cs:26:21:26:23 | access to local variable arg | BreakInTry.cs:26:28:26:31 | null | semmle.label | successor | -| BreakInTry.cs:26:21:26:31 | ... == ... | BreakInTry.cs:27:21:27:26 | break; | semmle.label | true | -| BreakInTry.cs:26:21:26:31 | ... == ... | BreakInTry.cs:30:13:33:13 | {...} | semmle.label | false | -| BreakInTry.cs:26:28:26:31 | null | BreakInTry.cs:26:21:26:31 | ... == ... | semmle.label | successor | -| BreakInTry.cs:27:21:27:26 | break; | BreakInTry.cs:30:13:33:13 | [finally: break] {...} | semmle.label | break | -| BreakInTry.cs:30:13:33:13 | [finally: break] {...} | BreakInTry.cs:31:17:32:21 | [finally: break] if (...) ... | semmle.label | successor | -| BreakInTry.cs:30:13:33:13 | {...} | BreakInTry.cs:31:17:32:21 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:31:17:32:21 | [finally: break] if (...) ... | BreakInTry.cs:31:21:31:24 | [finally: break] access to parameter args | semmle.label | successor | -| BreakInTry.cs:31:17:32:21 | if (...) ... | BreakInTry.cs:31:21:31:24 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:31:21:31:24 | [finally: break] access to parameter args | BreakInTry.cs:31:29:31:32 | [finally: break] null | semmle.label | successor | -| BreakInTry.cs:31:21:31:24 | access to parameter args | BreakInTry.cs:31:29:31:32 | null | semmle.label | successor | -| BreakInTry.cs:31:21:31:32 | ... == ... | BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:31:21:31:32 | ... == ... | BreakInTry.cs:32:21:32:21 | ; | semmle.label | true | -| BreakInTry.cs:31:21:31:32 | [finally: break] ... == ... | BreakInTry.cs:32:21:32:21 | [finally: break] ; | semmle.label | true | -| BreakInTry.cs:31:21:31:32 | [finally: break] ... == ... | BreakInTry.cs:35:7:35:7 | ; | semmle.label | false | -| BreakInTry.cs:31:29:31:32 | [finally: break] null | BreakInTry.cs:31:21:31:32 | [finally: break] ... == ... | semmle.label | successor | -| BreakInTry.cs:31:29:31:32 | null | BreakInTry.cs:31:21:31:32 | ... == ... | semmle.label | successor | -| BreakInTry.cs:32:21:32:21 | ; | BreakInTry.cs:22:9:34:9 | foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:32:21:32:21 | [finally: break] ; | BreakInTry.cs:35:7:35:7 | ; | semmle.label | break | -| BreakInTry.cs:35:7:35:7 | ; | BreakInTry.cs:20:10:20:11 | exit M2 (normal) | semmle.label | successor | -| BreakInTry.cs:38:10:38:11 | enter M3 | BreakInTry.cs:39:5:54:5 | {...} | semmle.label | successor | -| BreakInTry.cs:38:10:38:11 | exit M3 (normal) | BreakInTry.cs:38:10:38:11 | exit M3 | semmle.label | successor | -| BreakInTry.cs:39:5:54:5 | {...} | BreakInTry.cs:40:9:52:9 | try {...} ... | semmle.label | successor | -| BreakInTry.cs:40:9:52:9 | try {...} ... | BreakInTry.cs:41:9:44:9 | {...} | semmle.label | successor | -| BreakInTry.cs:41:9:44:9 | {...} | BreakInTry.cs:42:13:43:23 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:42:13:43:23 | if (...) ... | BreakInTry.cs:42:17:42:20 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:42:17:42:20 | access to parameter args | BreakInTry.cs:42:25:42:28 | null | semmle.label | successor | -| BreakInTry.cs:42:17:42:28 | ... == ... | BreakInTry.cs:43:17:43:23 | return ...; | semmle.label | true | -| BreakInTry.cs:42:17:42:28 | ... == ... | BreakInTry.cs:46:9:52:9 | {...} | semmle.label | false | -| BreakInTry.cs:42:25:42:28 | null | BreakInTry.cs:42:17:42:28 | ... == ... | semmle.label | successor | -| BreakInTry.cs:43:17:43:23 | return ...; | BreakInTry.cs:46:9:52:9 | [finally: return] {...} | semmle.label | return | -| BreakInTry.cs:46:9:52:9 | [finally: return] {...} | BreakInTry.cs:47:33:47:36 | [finally: return] access to parameter args | semmle.label | successor | -| BreakInTry.cs:46:9:52:9 | {...} | BreakInTry.cs:47:33:47:36 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:47:13:51:13 | [finally: return] foreach (... ... in ...) ... | BreakInTry.cs:38:10:38:11 | exit M3 (normal) | semmle.label | return | -| BreakInTry.cs:47:13:51:13 | [finally: return] foreach (... ... in ...) ... | BreakInTry.cs:47:26:47:28 | [finally: return] String arg | semmle.label | non-empty | -| BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | BreakInTry.cs:47:26:47:28 | String arg | semmle.label | non-empty | -| BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | BreakInTry.cs:53:7:53:7 | ; | semmle.label | empty | -| BreakInTry.cs:47:26:47:28 | String arg | BreakInTry.cs:48:13:51:13 | {...} | semmle.label | successor | -| BreakInTry.cs:47:26:47:28 | [finally: return] String arg | BreakInTry.cs:48:13:51:13 | [finally: return] {...} | semmle.label | successor | -| BreakInTry.cs:47:33:47:36 | [finally: return] access to parameter args | BreakInTry.cs:47:13:51:13 | [finally: return] foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:47:33:47:36 | access to parameter args | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:48:13:51:13 | [finally: return] {...} | BreakInTry.cs:49:17:50:26 | [finally: return] if (...) ... | semmle.label | successor | -| BreakInTry.cs:48:13:51:13 | {...} | BreakInTry.cs:49:17:50:26 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:49:17:50:26 | [finally: return] if (...) ... | BreakInTry.cs:49:21:49:23 | [finally: return] access to local variable arg | semmle.label | successor | -| BreakInTry.cs:49:17:50:26 | if (...) ... | BreakInTry.cs:49:21:49:23 | access to local variable arg | semmle.label | successor | -| BreakInTry.cs:49:21:49:23 | [finally: return] access to local variable arg | BreakInTry.cs:49:28:49:31 | [finally: return] null | semmle.label | successor | -| BreakInTry.cs:49:21:49:23 | access to local variable arg | BreakInTry.cs:49:28:49:31 | null | semmle.label | successor | -| BreakInTry.cs:49:21:49:31 | ... == ... | BreakInTry.cs:47:13:51:13 | foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:49:21:49:31 | ... == ... | BreakInTry.cs:50:21:50:26 | break; | semmle.label | true | -| BreakInTry.cs:49:21:49:31 | [finally: return] ... == ... | BreakInTry.cs:47:13:51:13 | [finally: return] foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:49:21:49:31 | [finally: return] ... == ... | BreakInTry.cs:50:21:50:26 | [finally: return] break; | semmle.label | true | -| BreakInTry.cs:49:28:49:31 | [finally: return] null | BreakInTry.cs:49:21:49:31 | [finally: return] ... == ... | semmle.label | successor | -| BreakInTry.cs:49:28:49:31 | null | BreakInTry.cs:49:21:49:31 | ... == ... | semmle.label | successor | -| BreakInTry.cs:50:21:50:26 | [finally: return] break; | BreakInTry.cs:38:10:38:11 | exit M3 (normal) | semmle.label | return | -| BreakInTry.cs:50:21:50:26 | break; | BreakInTry.cs:53:7:53:7 | ; | semmle.label | break | -| BreakInTry.cs:53:7:53:7 | ; | BreakInTry.cs:38:10:38:11 | exit M3 (normal) | semmle.label | successor | -| BreakInTry.cs:56:10:56:11 | enter M4 | BreakInTry.cs:57:5:71:5 | {...} | semmle.label | successor | -| BreakInTry.cs:56:10:56:11 | exit M4 (normal) | BreakInTry.cs:56:10:56:11 | exit M4 | semmle.label | successor | -| BreakInTry.cs:57:5:71:5 | {...} | BreakInTry.cs:58:9:70:9 | try {...} ... | semmle.label | successor | -| BreakInTry.cs:58:9:70:9 | try {...} ... | BreakInTry.cs:59:9:62:9 | {...} | semmle.label | successor | -| BreakInTry.cs:59:9:62:9 | {...} | BreakInTry.cs:60:13:61:23 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:60:13:61:23 | if (...) ... | BreakInTry.cs:60:17:60:20 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:60:17:60:20 | access to parameter args | BreakInTry.cs:60:25:60:28 | null | semmle.label | successor | -| BreakInTry.cs:60:17:60:28 | ... == ... | BreakInTry.cs:61:17:61:23 | return ...; | semmle.label | true | -| BreakInTry.cs:60:17:60:28 | ... == ... | BreakInTry.cs:64:9:70:9 | {...} | semmle.label | false | -| BreakInTry.cs:60:25:60:28 | null | BreakInTry.cs:60:17:60:28 | ... == ... | semmle.label | successor | -| BreakInTry.cs:61:17:61:23 | return ...; | BreakInTry.cs:64:9:70:9 | [finally: return] {...} | semmle.label | return | -| BreakInTry.cs:64:9:70:9 | [finally: return] {...} | BreakInTry.cs:65:33:65:36 | [finally: return] access to parameter args | semmle.label | successor | -| BreakInTry.cs:64:9:70:9 | {...} | BreakInTry.cs:65:33:65:36 | access to parameter args | semmle.label | successor | -| BreakInTry.cs:65:13:69:13 | [finally: return] foreach (... ... in ...) ... | BreakInTry.cs:56:10:56:11 | exit M4 (normal) | semmle.label | return | -| BreakInTry.cs:65:13:69:13 | [finally: return] foreach (... ... in ...) ... | BreakInTry.cs:65:26:65:28 | [finally: return] String arg | semmle.label | non-empty | -| BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | BreakInTry.cs:56:10:56:11 | exit M4 (normal) | semmle.label | empty | -| BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | BreakInTry.cs:65:26:65:28 | String arg | semmle.label | non-empty | -| BreakInTry.cs:65:26:65:28 | String arg | BreakInTry.cs:66:13:69:13 | {...} | semmle.label | successor | -| BreakInTry.cs:65:26:65:28 | [finally: return] String arg | BreakInTry.cs:66:13:69:13 | [finally: return] {...} | semmle.label | successor | -| BreakInTry.cs:65:33:65:36 | [finally: return] access to parameter args | BreakInTry.cs:65:13:69:13 | [finally: return] foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:65:33:65:36 | access to parameter args | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | semmle.label | successor | -| BreakInTry.cs:66:13:69:13 | [finally: return] {...} | BreakInTry.cs:67:17:68:26 | [finally: return] if (...) ... | semmle.label | successor | -| BreakInTry.cs:66:13:69:13 | {...} | BreakInTry.cs:67:17:68:26 | if (...) ... | semmle.label | successor | -| BreakInTry.cs:67:17:68:26 | [finally: return] if (...) ... | BreakInTry.cs:67:21:67:23 | [finally: return] access to local variable arg | semmle.label | successor | -| BreakInTry.cs:67:17:68:26 | if (...) ... | BreakInTry.cs:67:21:67:23 | access to local variable arg | semmle.label | successor | -| BreakInTry.cs:67:21:67:23 | [finally: return] access to local variable arg | BreakInTry.cs:67:28:67:31 | [finally: return] null | semmle.label | successor | -| BreakInTry.cs:67:21:67:23 | access to local variable arg | BreakInTry.cs:67:28:67:31 | null | semmle.label | successor | -| BreakInTry.cs:67:21:67:31 | ... == ... | BreakInTry.cs:65:13:69:13 | foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:67:21:67:31 | ... == ... | BreakInTry.cs:68:21:68:26 | break; | semmle.label | true | -| BreakInTry.cs:67:21:67:31 | [finally: return] ... == ... | BreakInTry.cs:65:13:69:13 | [finally: return] foreach (... ... in ...) ... | semmle.label | false | -| BreakInTry.cs:67:21:67:31 | [finally: return] ... == ... | BreakInTry.cs:68:21:68:26 | [finally: return] break; | semmle.label | true | -| BreakInTry.cs:67:28:67:31 | [finally: return] null | BreakInTry.cs:67:21:67:31 | [finally: return] ... == ... | semmle.label | successor | -| BreakInTry.cs:67:28:67:31 | null | BreakInTry.cs:67:21:67:31 | ... == ... | semmle.label | successor | -| BreakInTry.cs:68:21:68:26 | [finally: return] break; | BreakInTry.cs:56:10:56:11 | exit M4 (normal) | semmle.label | return | -| BreakInTry.cs:68:21:68:26 | break; | BreakInTry.cs:56:10:56:11 | exit M4 (normal) | semmle.label | break | -| CompileTimeOperators.cs:5:9:5:15 | enter Default | CompileTimeOperators.cs:6:5:8:5 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:5:9:5:15 | exit Default (normal) | CompileTimeOperators.cs:5:9:5:15 | exit Default | semmle.label | successor | -| CompileTimeOperators.cs:6:5:8:5 | {...} | CompileTimeOperators.cs:7:16:7:27 | default(...) | semmle.label | successor | -| CompileTimeOperators.cs:7:9:7:28 | return ...; | CompileTimeOperators.cs:5:9:5:15 | exit Default (normal) | semmle.label | return | -| CompileTimeOperators.cs:7:16:7:27 | default(...) | CompileTimeOperators.cs:7:9:7:28 | return ...; | semmle.label | successor | -| CompileTimeOperators.cs:10:9:10:14 | enter Sizeof | CompileTimeOperators.cs:11:5:13:5 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:10:9:10:14 | exit Sizeof (normal) | CompileTimeOperators.cs:10:9:10:14 | exit Sizeof | semmle.label | successor | -| CompileTimeOperators.cs:11:5:13:5 | {...} | CompileTimeOperators.cs:12:16:12:26 | sizeof(..) | semmle.label | successor | -| CompileTimeOperators.cs:12:9:12:27 | return ...; | CompileTimeOperators.cs:10:9:10:14 | exit Sizeof (normal) | semmle.label | return | -| CompileTimeOperators.cs:12:16:12:26 | sizeof(..) | CompileTimeOperators.cs:12:9:12:27 | return ...; | semmle.label | successor | -| CompileTimeOperators.cs:15:10:15:15 | enter Typeof | CompileTimeOperators.cs:16:5:18:5 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:15:10:15:15 | exit Typeof (normal) | CompileTimeOperators.cs:15:10:15:15 | exit Typeof | semmle.label | successor | -| CompileTimeOperators.cs:16:5:18:5 | {...} | CompileTimeOperators.cs:17:16:17:26 | typeof(...) | semmle.label | successor | -| CompileTimeOperators.cs:17:9:17:27 | return ...; | CompileTimeOperators.cs:15:10:15:15 | exit Typeof (normal) | semmle.label | return | -| CompileTimeOperators.cs:17:16:17:26 | typeof(...) | CompileTimeOperators.cs:17:9:17:27 | return ...; | semmle.label | successor | -| CompileTimeOperators.cs:20:12:20:17 | enter Nameof | CompileTimeOperators.cs:21:5:23:5 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:20:12:20:17 | exit Nameof (normal) | CompileTimeOperators.cs:20:12:20:17 | exit Nameof | semmle.label | successor | -| CompileTimeOperators.cs:21:5:23:5 | {...} | CompileTimeOperators.cs:22:16:22:24 | nameof(...) | semmle.label | successor | -| CompileTimeOperators.cs:22:9:22:25 | return ...; | CompileTimeOperators.cs:20:12:20:17 | exit Nameof (normal) | semmle.label | return | -| CompileTimeOperators.cs:22:16:22:24 | nameof(...) | CompileTimeOperators.cs:22:9:22:25 | return ...; | semmle.label | successor | -| CompileTimeOperators.cs:28:10:28:10 | enter M | CompileTimeOperators.cs:29:5:41:5 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:28:10:28:10 | exit M (normal) | CompileTimeOperators.cs:28:10:28:10 | exit M | semmle.label | successor | -| CompileTimeOperators.cs:29:5:41:5 | {...} | CompileTimeOperators.cs:30:9:38:9 | try {...} ... | semmle.label | successor | -| CompileTimeOperators.cs:30:9:38:9 | try {...} ... | CompileTimeOperators.cs:31:9:34:9 | {...} | semmle.label | successor | -| CompileTimeOperators.cs:31:9:34:9 | {...} | CompileTimeOperators.cs:32:13:32:21 | goto ...; | semmle.label | successor | -| CompileTimeOperators.cs:32:13:32:21 | goto ...; | CompileTimeOperators.cs:36:9:38:9 | [finally: goto(End)] {...} | semmle.label | goto(End) | -| CompileTimeOperators.cs:36:9:38:9 | [finally: goto(End)] {...} | CompileTimeOperators.cs:37:13:37:41 | [finally: goto(End)] ...; | semmle.label | successor | -| CompileTimeOperators.cs:37:13:37:40 | [finally: goto(End)] call to method WriteLine | CompileTimeOperators.cs:40:9:40:11 | End: | semmle.label | goto(End) | -| CompileTimeOperators.cs:37:13:37:41 | [finally: goto(End)] ...; | CompileTimeOperators.cs:37:31:37:39 | [finally: goto(End)] "Finally" | semmle.label | successor | -| CompileTimeOperators.cs:37:31:37:39 | [finally: goto(End)] "Finally" | CompileTimeOperators.cs:37:13:37:40 | [finally: goto(End)] call to method WriteLine | semmle.label | successor | -| CompileTimeOperators.cs:40:9:40:11 | End: | CompileTimeOperators.cs:40:14:40:38 | ...; | semmle.label | successor | -| CompileTimeOperators.cs:40:14:40:37 | call to method WriteLine | CompileTimeOperators.cs:28:10:28:10 | exit M (normal) | semmle.label | successor | -| CompileTimeOperators.cs:40:14:40:38 | ...; | CompileTimeOperators.cs:40:32:40:36 | "End" | semmle.label | successor | -| CompileTimeOperators.cs:40:32:40:36 | "End" | CompileTimeOperators.cs:40:14:40:37 | call to method WriteLine | semmle.label | successor | -| ConditionalAccess.cs:3:12:3:13 | enter M1 | ConditionalAccess.cs:3:26:3:26 | access to parameter i | semmle.label | successor | -| ConditionalAccess.cs:3:12:3:13 | exit M1 (normal) | ConditionalAccess.cs:3:12:3:13 | exit M1 | semmle.label | successor | -| ConditionalAccess.cs:3:26:3:26 | access to parameter i | ConditionalAccess.cs:3:12:3:13 | exit M1 (normal) | semmle.label | null | -| ConditionalAccess.cs:3:26:3:26 | access to parameter i | ConditionalAccess.cs:3:28:3:38 | call to method ToString | semmle.label | non-null | -| ConditionalAccess.cs:3:28:3:38 | call to method ToString | ConditionalAccess.cs:3:12:3:13 | exit M1 (normal) | semmle.label | null | -| ConditionalAccess.cs:3:28:3:38 | call to method ToString | ConditionalAccess.cs:3:40:3:49 | call to method ToLower | semmle.label | non-null | -| ConditionalAccess.cs:3:40:3:49 | call to method ToLower | ConditionalAccess.cs:3:12:3:13 | exit M1 (normal) | semmle.label | successor | -| ConditionalAccess.cs:5:10:5:11 | enter M2 | ConditionalAccess.cs:5:26:5:26 | access to parameter s | semmle.label | successor | -| ConditionalAccess.cs:5:10:5:11 | exit M2 (normal) | ConditionalAccess.cs:5:10:5:11 | exit M2 | semmle.label | successor | -| ConditionalAccess.cs:5:26:5:26 | access to parameter s | ConditionalAccess.cs:5:10:5:11 | exit M2 (normal) | semmle.label | null | -| ConditionalAccess.cs:5:26:5:26 | access to parameter s | ConditionalAccess.cs:5:28:5:34 | access to property Length | semmle.label | non-null | -| ConditionalAccess.cs:5:28:5:34 | access to property Length | ConditionalAccess.cs:5:10:5:11 | exit M2 (normal) | semmle.label | successor | -| ConditionalAccess.cs:7:10:7:11 | enter M3 | ConditionalAccess.cs:7:39:7:40 | access to parameter s1 | semmle.label | successor | -| ConditionalAccess.cs:7:10:7:11 | exit M3 (normal) | ConditionalAccess.cs:7:10:7:11 | exit M3 | semmle.label | successor | -| ConditionalAccess.cs:7:39:7:40 | access to parameter s1 | ConditionalAccess.cs:7:39:7:46 | ... ?? ... | semmle.label | non-null | -| ConditionalAccess.cs:7:39:7:40 | access to parameter s1 | ConditionalAccess.cs:7:45:7:46 | access to parameter s2 | semmle.label | null | -| ConditionalAccess.cs:7:39:7:46 | ... ?? ... | ConditionalAccess.cs:7:10:7:11 | exit M3 (normal) | semmle.label | null | -| ConditionalAccess.cs:7:39:7:46 | ... ?? ... | ConditionalAccess.cs:7:49:7:55 | access to property Length | semmle.label | non-null | -| ConditionalAccess.cs:7:39:7:46 | [non-null] ... ?? ... | ConditionalAccess.cs:7:49:7:55 | access to property Length | semmle.label | non-null | -| ConditionalAccess.cs:7:39:7:46 | [null] ... ?? ... | ConditionalAccess.cs:7:10:7:11 | exit M3 (normal) | semmle.label | null | -| ConditionalAccess.cs:7:45:7:46 | access to parameter s2 | ConditionalAccess.cs:7:39:7:46 | [non-null] ... ?? ... | semmle.label | non-null | -| ConditionalAccess.cs:7:45:7:46 | access to parameter s2 | ConditionalAccess.cs:7:39:7:46 | [null] ... ?? ... | semmle.label | null | -| ConditionalAccess.cs:7:49:7:55 | access to property Length | ConditionalAccess.cs:7:10:7:11 | exit M3 (normal) | semmle.label | successor | -| ConditionalAccess.cs:9:9:9:10 | enter M4 | ConditionalAccess.cs:9:25:9:25 | access to parameter s | semmle.label | successor | -| ConditionalAccess.cs:9:9:9:10 | exit M4 (normal) | ConditionalAccess.cs:9:9:9:10 | exit M4 | semmle.label | successor | -| ConditionalAccess.cs:9:25:9:25 | access to parameter s | ConditionalAccess.cs:9:27:9:33 | access to property Length | semmle.label | non-null | -| ConditionalAccess.cs:9:25:9:25 | access to parameter s | ConditionalAccess.cs:9:38:9:38 | 0 | semmle.label | null | -| ConditionalAccess.cs:9:25:9:38 | ... ?? ... | ConditionalAccess.cs:9:9:9:10 | exit M4 (normal) | semmle.label | successor | -| ConditionalAccess.cs:9:27:9:33 | access to property Length | ConditionalAccess.cs:9:25:9:38 | ... ?? ... | semmle.label | non-null | -| ConditionalAccess.cs:9:27:9:33 | access to property Length | ConditionalAccess.cs:9:38:9:38 | 0 | semmle.label | null | -| ConditionalAccess.cs:9:38:9:38 | 0 | ConditionalAccess.cs:9:25:9:38 | ... ?? ... | semmle.label | successor | -| ConditionalAccess.cs:11:9:11:10 | enter M5 | ConditionalAccess.cs:12:5:17:5 | {...} | semmle.label | successor | -| ConditionalAccess.cs:11:9:11:10 | exit M5 (normal) | ConditionalAccess.cs:11:9:11:10 | exit M5 | semmle.label | successor | -| ConditionalAccess.cs:12:5:17:5 | {...} | ConditionalAccess.cs:13:9:16:21 | if (...) ... | semmle.label | successor | -| ConditionalAccess.cs:13:9:16:21 | if (...) ... | ConditionalAccess.cs:13:13:13:13 | access to parameter s | semmle.label | successor | -| ConditionalAccess.cs:13:13:13:13 | access to parameter s | ConditionalAccess.cs:13:15:13:21 | access to property Length | semmle.label | non-null | -| ConditionalAccess.cs:13:13:13:13 | access to parameter s | ConditionalAccess.cs:13:25:13:25 | 0 | semmle.label | null | -| ConditionalAccess.cs:13:13:13:25 | ... > ... | ConditionalAccess.cs:14:20:14:20 | 0 | semmle.label | true | -| ConditionalAccess.cs:13:13:13:25 | ... > ... | ConditionalAccess.cs:16:20:16:20 | 1 | semmle.label | false | -| ConditionalAccess.cs:13:15:13:21 | access to property Length | ConditionalAccess.cs:13:25:13:25 | 0 | semmle.label | successor | -| ConditionalAccess.cs:13:25:13:25 | 0 | ConditionalAccess.cs:13:25:13:25 | (...) ... | semmle.label | successor | -| ConditionalAccess.cs:13:25:13:25 | (...) ... | ConditionalAccess.cs:13:13:13:25 | ... > ... | semmle.label | successor | -| ConditionalAccess.cs:14:13:14:21 | return ...; | ConditionalAccess.cs:11:9:11:10 | exit M5 (normal) | semmle.label | return | -| ConditionalAccess.cs:14:20:14:20 | 0 | ConditionalAccess.cs:14:13:14:21 | return ...; | semmle.label | successor | -| ConditionalAccess.cs:16:13:16:21 | return ...; | ConditionalAccess.cs:11:9:11:10 | exit M5 (normal) | semmle.label | return | -| ConditionalAccess.cs:16:20:16:20 | 1 | ConditionalAccess.cs:16:13:16:21 | return ...; | semmle.label | successor | -| ConditionalAccess.cs:19:12:19:13 | enter M6 | ConditionalAccess.cs:19:40:19:41 | access to parameter s1 | semmle.label | successor | -| ConditionalAccess.cs:19:12:19:13 | exit M6 (normal) | ConditionalAccess.cs:19:12:19:13 | exit M6 | semmle.label | successor | -| ConditionalAccess.cs:19:40:19:41 | access to parameter s1 | ConditionalAccess.cs:19:12:19:13 | exit M6 (normal) | semmle.label | null | -| ConditionalAccess.cs:19:40:19:41 | access to parameter s1 | ConditionalAccess.cs:19:58:19:59 | access to parameter s2 | semmle.label | non-null | -| ConditionalAccess.cs:19:43:19:60 | call to method CommaJoinWith | ConditionalAccess.cs:19:12:19:13 | exit M6 (normal) | semmle.label | successor | -| ConditionalAccess.cs:19:58:19:59 | access to parameter s2 | ConditionalAccess.cs:19:43:19:60 | call to method CommaJoinWith | semmle.label | successor | -| ConditionalAccess.cs:21:10:21:11 | enter M7 | ConditionalAccess.cs:22:5:26:5 | {...} | semmle.label | successor | -| ConditionalAccess.cs:21:10:21:11 | exit M7 (normal) | ConditionalAccess.cs:21:10:21:11 | exit M7 | semmle.label | successor | -| ConditionalAccess.cs:22:5:26:5 | {...} | ConditionalAccess.cs:23:9:23:39 | ... ...; | semmle.label | successor | -| ConditionalAccess.cs:23:9:23:39 | ... ...; | ConditionalAccess.cs:23:26:23:29 | null | semmle.label | successor | -| ConditionalAccess.cs:23:13:23:38 | Nullable j = ... | ConditionalAccess.cs:24:9:24:38 | ... ...; | semmle.label | successor | -| ConditionalAccess.cs:23:18:23:29 | (...) ... | ConditionalAccess.cs:23:13:23:38 | Nullable j = ... | semmle.label | null | -| ConditionalAccess.cs:23:26:23:29 | null | ConditionalAccess.cs:23:18:23:29 | (...) ... | semmle.label | successor | -| ConditionalAccess.cs:24:9:24:38 | ... ...; | ConditionalAccess.cs:24:24:24:24 | access to parameter i | semmle.label | successor | -| ConditionalAccess.cs:24:13:24:37 | String s = ... | ConditionalAccess.cs:25:9:25:33 | ...; | semmle.label | successor | -| ConditionalAccess.cs:24:18:24:24 | (...) ... | ConditionalAccess.cs:24:27:24:37 | call to method ToString | semmle.label | non-null | -| ConditionalAccess.cs:24:24:24:24 | access to parameter i | ConditionalAccess.cs:24:18:24:24 | (...) ... | semmle.label | successor | -| ConditionalAccess.cs:24:27:24:37 | call to method ToString | ConditionalAccess.cs:24:13:24:37 | String s = ... | semmle.label | successor | -| ConditionalAccess.cs:25:9:25:32 | ... = ... | ConditionalAccess.cs:21:10:21:11 | exit M7 (normal) | semmle.label | successor | -| ConditionalAccess.cs:25:9:25:33 | ...; | ConditionalAccess.cs:25:13:25:14 | "" | semmle.label | successor | -| ConditionalAccess.cs:25:13:25:14 | "" | ConditionalAccess.cs:25:31:25:31 | access to local variable s | semmle.label | non-null | -| ConditionalAccess.cs:25:16:25:32 | call to method CommaJoinWith | ConditionalAccess.cs:25:9:25:32 | ... = ... | semmle.label | successor | -| ConditionalAccess.cs:25:31:25:31 | access to local variable s | ConditionalAccess.cs:25:16:25:32 | call to method CommaJoinWith | semmle.label | successor | -| ConditionalAccess.cs:30:10:30:12 | enter Out | ConditionalAccess.cs:30:32:30:32 | 0 | semmle.label | successor | -| ConditionalAccess.cs:30:10:30:12 | exit Out (normal) | ConditionalAccess.cs:30:10:30:12 | exit Out | semmle.label | successor | -| ConditionalAccess.cs:30:28:30:32 | ... = ... | ConditionalAccess.cs:30:10:30:12 | exit Out (normal) | semmle.label | successor | -| ConditionalAccess.cs:30:32:30:32 | 0 | ConditionalAccess.cs:30:28:30:32 | ... = ... | semmle.label | successor | -| ConditionalAccess.cs:32:10:32:11 | enter M8 | ConditionalAccess.cs:33:5:36:5 | {...} | semmle.label | successor | -| ConditionalAccess.cs:32:10:32:11 | exit M8 (normal) | ConditionalAccess.cs:32:10:32:11 | exit M8 | semmle.label | successor | -| ConditionalAccess.cs:33:5:36:5 | {...} | ConditionalAccess.cs:34:9:34:14 | ...; | semmle.label | successor | -| ConditionalAccess.cs:34:9:34:13 | ... = ... | ConditionalAccess.cs:35:9:35:25 | ...; | semmle.label | successor | -| ConditionalAccess.cs:34:9:34:14 | ...; | ConditionalAccess.cs:34:13:34:13 | 0 | semmle.label | successor | -| ConditionalAccess.cs:34:13:34:13 | 0 | ConditionalAccess.cs:34:9:34:13 | ... = ... | semmle.label | successor | -| ConditionalAccess.cs:35:9:35:12 | access to property Prop | ConditionalAccess.cs:32:10:32:11 | exit M8 (normal) | semmle.label | null | -| ConditionalAccess.cs:35:9:35:12 | access to property Prop | ConditionalAccess.cs:35:14:35:24 | call to method Out | semmle.label | non-null | -| ConditionalAccess.cs:35:9:35:12 | this access | ConditionalAccess.cs:35:9:35:12 | access to property Prop | semmle.label | successor | -| ConditionalAccess.cs:35:9:35:25 | ...; | ConditionalAccess.cs:35:9:35:12 | this access | semmle.label | successor | -| ConditionalAccess.cs:35:14:35:24 | call to method Out | ConditionalAccess.cs:32:10:32:11 | exit M8 (normal) | semmle.label | successor | -| ConditionalAccess.cs:41:26:41:38 | enter CommaJoinWith | ConditionalAccess.cs:41:70:41:71 | access to parameter s1 | semmle.label | successor | -| ConditionalAccess.cs:41:26:41:38 | exit CommaJoinWith (normal) | ConditionalAccess.cs:41:26:41:38 | exit CommaJoinWith | semmle.label | successor | -| ConditionalAccess.cs:41:70:41:71 | access to parameter s1 | ConditionalAccess.cs:41:75:41:78 | ", " | semmle.label | successor | -| ConditionalAccess.cs:41:70:41:78 | ... + ... | ConditionalAccess.cs:41:82:41:83 | access to parameter s2 | semmle.label | successor | -| ConditionalAccess.cs:41:70:41:83 | ... + ... | ConditionalAccess.cs:41:26:41:38 | exit CommaJoinWith (normal) | semmle.label | successor | -| ConditionalAccess.cs:41:75:41:78 | ", " | ConditionalAccess.cs:41:70:41:78 | ... + ... | semmle.label | successor | -| ConditionalAccess.cs:41:82:41:83 | access to parameter s2 | ConditionalAccess.cs:41:70:41:83 | ... + ... | semmle.label | successor | -| Conditions.cs:3:10:3:19 | enter IncrOrDecr | Conditions.cs:4:5:9:5 | {...} | semmle.label | successor | -| Conditions.cs:3:10:3:19 | exit IncrOrDecr (normal) | Conditions.cs:3:10:3:19 | exit IncrOrDecr | semmle.label | successor | -| Conditions.cs:4:5:9:5 | {...} | Conditions.cs:5:9:6:16 | if (...) ... | semmle.label | successor | -| Conditions.cs:5:9:6:16 | if (...) ... | Conditions.cs:5:13:5:15 | access to parameter inc | semmle.label | successor | -| Conditions.cs:5:13:5:15 | access to parameter inc | Conditions.cs:6:13:6:16 | [inc (line 3): true] ...; | semmle.label | true | -| Conditions.cs:5:13:5:15 | access to parameter inc | Conditions.cs:7:9:8:16 | [inc (line 3): false] if (...) ... | semmle.label | false | -| Conditions.cs:6:13:6:13 | [inc (line 3): true] access to parameter x | Conditions.cs:6:13:6:15 | [inc (line 3): true] ...++ | semmle.label | successor | -| Conditions.cs:6:13:6:15 | [inc (line 3): true] ...++ | Conditions.cs:7:9:8:16 | [inc (line 3): true] if (...) ... | semmle.label | successor | -| Conditions.cs:6:13:6:16 | [inc (line 3): true] ...; | Conditions.cs:6:13:6:13 | [inc (line 3): true] access to parameter x | semmle.label | successor | -| Conditions.cs:7:9:8:16 | [inc (line 3): false] if (...) ... | Conditions.cs:7:14:7:16 | [inc (line 3): false] access to parameter inc | semmle.label | successor | -| Conditions.cs:7:9:8:16 | [inc (line 3): true] if (...) ... | Conditions.cs:7:14:7:16 | [inc (line 3): true] access to parameter inc | semmle.label | successor | -| Conditions.cs:7:13:7:16 | [false] !... | Conditions.cs:3:10:3:19 | exit IncrOrDecr (normal) | semmle.label | false | -| Conditions.cs:7:13:7:16 | [true] !... | Conditions.cs:8:13:8:16 | ...; | semmle.label | true | -| Conditions.cs:7:14:7:16 | [inc (line 3): false] access to parameter inc | Conditions.cs:7:13:7:16 | [true] !... | semmle.label | false | -| Conditions.cs:7:14:7:16 | [inc (line 3): true] access to parameter inc | Conditions.cs:7:13:7:16 | [false] !... | semmle.label | true | -| Conditions.cs:8:13:8:13 | access to parameter x | Conditions.cs:8:13:8:15 | ...-- | semmle.label | successor | -| Conditions.cs:8:13:8:15 | ...-- | Conditions.cs:3:10:3:19 | exit IncrOrDecr (normal) | semmle.label | successor | -| Conditions.cs:8:13:8:16 | ...; | Conditions.cs:8:13:8:13 | access to parameter x | semmle.label | successor | -| Conditions.cs:11:9:11:10 | enter M1 | Conditions.cs:12:5:20:5 | {...} | semmle.label | successor | -| Conditions.cs:11:9:11:10 | exit M1 (normal) | Conditions.cs:11:9:11:10 | exit M1 | semmle.label | successor | -| Conditions.cs:12:5:20:5 | {...} | Conditions.cs:13:9:13:18 | ... ...; | semmle.label | successor | -| Conditions.cs:13:9:13:18 | ... ...; | Conditions.cs:13:17:13:17 | 0 | semmle.label | successor | -| Conditions.cs:13:13:13:17 | Int32 x = ... | Conditions.cs:14:9:15:16 | if (...) ... | semmle.label | successor | -| Conditions.cs:13:17:13:17 | 0 | Conditions.cs:13:13:13:17 | Int32 x = ... | semmle.label | successor | -| Conditions.cs:14:9:15:16 | if (...) ... | Conditions.cs:14:13:14:13 | access to parameter b | semmle.label | successor | -| Conditions.cs:14:13:14:13 | access to parameter b | Conditions.cs:15:13:15:16 | [b (line 11): true] ...; | semmle.label | true | -| Conditions.cs:14:13:14:13 | access to parameter b | Conditions.cs:16:9:18:20 | [b (line 11): false] if (...) ... | semmle.label | false | -| Conditions.cs:15:13:15:13 | [b (line 11): true] access to local variable x | Conditions.cs:15:13:15:15 | [b (line 11): true] ...++ | semmle.label | successor | -| Conditions.cs:15:13:15:15 | [b (line 11): true] ...++ | Conditions.cs:16:9:18:20 | [b (line 11): true] if (...) ... | semmle.label | successor | -| Conditions.cs:15:13:15:16 | [b (line 11): true] ...; | Conditions.cs:15:13:15:13 | [b (line 11): true] access to local variable x | semmle.label | successor | -| Conditions.cs:16:9:18:20 | [b (line 11): false] if (...) ... | Conditions.cs:16:13:16:13 | [b (line 11): false] access to local variable x | semmle.label | successor | -| Conditions.cs:16:9:18:20 | [b (line 11): true] if (...) ... | Conditions.cs:16:13:16:13 | [b (line 11): true] access to local variable x | semmle.label | successor | -| Conditions.cs:16:13:16:13 | [b (line 11): false] access to local variable x | Conditions.cs:16:17:16:17 | [b (line 11): false] 0 | semmle.label | successor | -| Conditions.cs:16:13:16:13 | [b (line 11): true] access to local variable x | Conditions.cs:16:17:16:17 | [b (line 11): true] 0 | semmle.label | successor | -| Conditions.cs:16:13:16:17 | [b (line 11): false] ... > ... | Conditions.cs:17:13:18:20 | [b (line 11): false] if (...) ... | semmle.label | true | -| Conditions.cs:16:13:16:17 | [b (line 11): false] ... > ... | Conditions.cs:19:16:19:16 | access to local variable x | semmle.label | false | -| Conditions.cs:16:13:16:17 | [b (line 11): true] ... > ... | Conditions.cs:17:13:18:20 | [b (line 11): true] if (...) ... | semmle.label | true | -| Conditions.cs:16:13:16:17 | [b (line 11): true] ... > ... | Conditions.cs:19:16:19:16 | access to local variable x | semmle.label | false | -| Conditions.cs:16:17:16:17 | [b (line 11): false] 0 | Conditions.cs:16:13:16:17 | [b (line 11): false] ... > ... | semmle.label | successor | -| Conditions.cs:16:17:16:17 | [b (line 11): true] 0 | Conditions.cs:16:13:16:17 | [b (line 11): true] ... > ... | semmle.label | successor | -| Conditions.cs:17:13:18:20 | [b (line 11): false] if (...) ... | Conditions.cs:17:18:17:18 | [b (line 11): false] access to parameter b | semmle.label | successor | -| Conditions.cs:17:13:18:20 | [b (line 11): true] if (...) ... | Conditions.cs:17:18:17:18 | [b (line 11): true] access to parameter b | semmle.label | successor | -| Conditions.cs:17:17:17:18 | [false] !... | Conditions.cs:19:16:19:16 | access to local variable x | semmle.label | false | -| Conditions.cs:17:17:17:18 | [true] !... | Conditions.cs:18:17:18:20 | ...; | semmle.label | true | -| Conditions.cs:17:18:17:18 | [b (line 11): false] access to parameter b | Conditions.cs:17:17:17:18 | [true] !... | semmle.label | false | -| Conditions.cs:17:18:17:18 | [b (line 11): true] access to parameter b | Conditions.cs:17:17:17:18 | [false] !... | semmle.label | true | -| Conditions.cs:18:17:18:17 | access to local variable x | Conditions.cs:18:17:18:19 | ...-- | semmle.label | successor | -| Conditions.cs:18:17:18:19 | ...-- | Conditions.cs:19:16:19:16 | access to local variable x | semmle.label | successor | -| Conditions.cs:18:17:18:20 | ...; | Conditions.cs:18:17:18:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:19:9:19:17 | return ...; | Conditions.cs:11:9:11:10 | exit M1 (normal) | semmle.label | return | -| Conditions.cs:19:16:19:16 | access to local variable x | Conditions.cs:19:9:19:17 | return ...; | semmle.label | successor | -| Conditions.cs:22:9:22:10 | enter M2 | Conditions.cs:23:5:31:5 | {...} | semmle.label | successor | -| Conditions.cs:22:9:22:10 | exit M2 (normal) | Conditions.cs:22:9:22:10 | exit M2 | semmle.label | successor | -| Conditions.cs:23:5:31:5 | {...} | Conditions.cs:24:9:24:18 | ... ...; | semmle.label | successor | -| Conditions.cs:24:9:24:18 | ... ...; | Conditions.cs:24:17:24:17 | 0 | semmle.label | successor | -| Conditions.cs:24:13:24:17 | Int32 x = ... | Conditions.cs:25:9:27:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:24:17:24:17 | 0 | Conditions.cs:24:13:24:17 | Int32 x = ... | semmle.label | successor | -| Conditions.cs:25:9:27:20 | if (...) ... | Conditions.cs:25:13:25:14 | access to parameter b1 | semmle.label | successor | -| Conditions.cs:25:13:25:14 | access to parameter b1 | Conditions.cs:26:13:27:20 | if (...) ... | semmle.label | true | -| Conditions.cs:25:13:25:14 | access to parameter b1 | Conditions.cs:28:9:29:16 | if (...) ... | semmle.label | false | -| Conditions.cs:26:13:27:20 | if (...) ... | Conditions.cs:26:17:26:18 | access to parameter b2 | semmle.label | successor | -| Conditions.cs:26:17:26:18 | access to parameter b2 | Conditions.cs:27:17:27:20 | [b2 (line 22): true] ...; | semmle.label | true | -| Conditions.cs:26:17:26:18 | access to parameter b2 | Conditions.cs:28:9:29:16 | [b2 (line 22): false] if (...) ... | semmle.label | false | -| Conditions.cs:27:17:27:17 | [b2 (line 22): true] access to local variable x | Conditions.cs:27:17:27:19 | [b2 (line 22): true] ...++ | semmle.label | successor | -| Conditions.cs:27:17:27:19 | [b2 (line 22): true] ...++ | Conditions.cs:28:9:29:16 | [b2 (line 22): true] if (...) ... | semmle.label | successor | -| Conditions.cs:27:17:27:20 | [b2 (line 22): true] ...; | Conditions.cs:27:17:27:17 | [b2 (line 22): true] access to local variable x | semmle.label | successor | -| Conditions.cs:28:9:29:16 | [b2 (line 22): false] if (...) ... | Conditions.cs:28:13:28:14 | [b2 (line 22): false] access to parameter b2 | semmle.label | successor | -| Conditions.cs:28:9:29:16 | [b2 (line 22): true] if (...) ... | Conditions.cs:28:13:28:14 | [b2 (line 22): true] access to parameter b2 | semmle.label | successor | -| Conditions.cs:28:9:29:16 | if (...) ... | Conditions.cs:28:13:28:14 | access to parameter b2 | semmle.label | successor | -| Conditions.cs:28:13:28:14 | [b2 (line 22): false] access to parameter b2 | Conditions.cs:30:16:30:16 | access to local variable x | semmle.label | false | -| Conditions.cs:28:13:28:14 | [b2 (line 22): true] access to parameter b2 | Conditions.cs:29:13:29:16 | ...; | semmle.label | true | -| Conditions.cs:28:13:28:14 | access to parameter b2 | Conditions.cs:29:13:29:16 | ...; | semmle.label | true | -| Conditions.cs:28:13:28:14 | access to parameter b2 | Conditions.cs:30:16:30:16 | access to local variable x | semmle.label | false | -| Conditions.cs:29:13:29:13 | access to local variable x | Conditions.cs:29:13:29:15 | ...++ | semmle.label | successor | -| Conditions.cs:29:13:29:15 | ...++ | Conditions.cs:30:16:30:16 | access to local variable x | semmle.label | successor | -| Conditions.cs:29:13:29:16 | ...; | Conditions.cs:29:13:29:13 | access to local variable x | semmle.label | successor | -| Conditions.cs:30:9:30:17 | return ...; | Conditions.cs:22:9:22:10 | exit M2 (normal) | semmle.label | return | -| Conditions.cs:30:16:30:16 | access to local variable x | Conditions.cs:30:9:30:17 | return ...; | semmle.label | successor | -| Conditions.cs:33:9:33:10 | enter M3 | Conditions.cs:34:5:44:5 | {...} | semmle.label | successor | -| Conditions.cs:33:9:33:10 | exit M3 (normal) | Conditions.cs:33:9:33:10 | exit M3 | semmle.label | successor | -| Conditions.cs:34:5:44:5 | {...} | Conditions.cs:35:9:35:18 | ... ...; | semmle.label | successor | -| Conditions.cs:35:9:35:18 | ... ...; | Conditions.cs:35:17:35:17 | 0 | semmle.label | successor | -| Conditions.cs:35:13:35:17 | Int32 x = ... | Conditions.cs:36:9:36:23 | ... ...; | semmle.label | successor | -| Conditions.cs:35:17:35:17 | 0 | Conditions.cs:35:13:35:17 | Int32 x = ... | semmle.label | successor | -| Conditions.cs:36:9:36:23 | ... ...; | Conditions.cs:36:18:36:22 | false | semmle.label | successor | -| Conditions.cs:36:13:36:22 | Boolean b2 = ... | Conditions.cs:37:9:38:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:36:18:36:22 | false | Conditions.cs:36:13:36:22 | Boolean b2 = ... | semmle.label | successor | -| Conditions.cs:37:9:38:20 | if (...) ... | Conditions.cs:37:13:37:14 | access to parameter b1 | semmle.label | successor | -| Conditions.cs:37:13:37:14 | access to parameter b1 | Conditions.cs:38:13:38:20 | ...; | semmle.label | true | -| Conditions.cs:37:13:37:14 | access to parameter b1 | Conditions.cs:39:9:40:16 | if (...) ... | semmle.label | false | -| Conditions.cs:38:13:38:19 | ... = ... | Conditions.cs:39:9:40:16 | if (...) ... | semmle.label | successor | -| Conditions.cs:38:13:38:20 | ...; | Conditions.cs:38:18:38:19 | access to parameter b1 | semmle.label | successor | -| Conditions.cs:38:18:38:19 | access to parameter b1 | Conditions.cs:38:13:38:19 | ... = ... | semmle.label | successor | -| Conditions.cs:39:9:40:16 | if (...) ... | Conditions.cs:39:13:39:14 | access to local variable b2 | semmle.label | successor | -| Conditions.cs:39:13:39:14 | access to local variable b2 | Conditions.cs:40:13:40:16 | [b2 (line 39): true] ...; | semmle.label | true | -| Conditions.cs:39:13:39:14 | access to local variable b2 | Conditions.cs:41:9:42:16 | [b2 (line 39): false] if (...) ... | semmle.label | false | -| Conditions.cs:40:13:40:13 | [b2 (line 39): true] access to local variable x | Conditions.cs:40:13:40:15 | [b2 (line 39): true] ...++ | semmle.label | successor | -| Conditions.cs:40:13:40:15 | [b2 (line 39): true] ...++ | Conditions.cs:41:9:42:16 | [b2 (line 39): true] if (...) ... | semmle.label | successor | -| Conditions.cs:40:13:40:16 | [b2 (line 39): true] ...; | Conditions.cs:40:13:40:13 | [b2 (line 39): true] access to local variable x | semmle.label | successor | -| Conditions.cs:41:9:42:16 | [b2 (line 39): false] if (...) ... | Conditions.cs:41:13:41:14 | [b2 (line 39): false] access to local variable b2 | semmle.label | successor | -| Conditions.cs:41:9:42:16 | [b2 (line 39): true] if (...) ... | Conditions.cs:41:13:41:14 | [b2 (line 39): true] access to local variable b2 | semmle.label | successor | -| Conditions.cs:41:13:41:14 | [b2 (line 39): false] access to local variable b2 | Conditions.cs:43:16:43:16 | access to local variable x | semmle.label | false | -| Conditions.cs:41:13:41:14 | [b2 (line 39): true] access to local variable b2 | Conditions.cs:42:13:42:16 | ...; | semmle.label | true | -| Conditions.cs:42:13:42:13 | access to local variable x | Conditions.cs:42:13:42:15 | ...++ | semmle.label | successor | -| Conditions.cs:42:13:42:15 | ...++ | Conditions.cs:43:16:43:16 | access to local variable x | semmle.label | successor | -| Conditions.cs:42:13:42:16 | ...; | Conditions.cs:42:13:42:13 | access to local variable x | semmle.label | successor | -| Conditions.cs:43:9:43:17 | return ...; | Conditions.cs:33:9:33:10 | exit M3 (normal) | semmle.label | return | -| Conditions.cs:43:16:43:16 | access to local variable x | Conditions.cs:43:9:43:17 | return ...; | semmle.label | successor | -| Conditions.cs:46:9:46:10 | enter M4 | Conditions.cs:47:5:55:5 | {...} | semmle.label | successor | -| Conditions.cs:46:9:46:10 | exit M4 (normal) | Conditions.cs:46:9:46:10 | exit M4 | semmle.label | successor | -| Conditions.cs:47:5:55:5 | {...} | Conditions.cs:48:9:48:18 | ... ...; | semmle.label | successor | -| Conditions.cs:48:9:48:18 | ... ...; | Conditions.cs:48:17:48:17 | 0 | semmle.label | successor | -| Conditions.cs:48:13:48:17 | Int32 y = ... | Conditions.cs:49:9:53:9 | while (...) ... | semmle.label | successor | -| Conditions.cs:48:17:48:17 | 0 | Conditions.cs:48:13:48:17 | Int32 y = ... | semmle.label | successor | -| Conditions.cs:49:9:53:9 | while (...) ... | Conditions.cs:49:16:49:16 | access to parameter x | semmle.label | successor | -| Conditions.cs:49:16:49:16 | [b (line 46): false] access to parameter x | Conditions.cs:49:16:49:18 | [b (line 46): false] ...-- | semmle.label | successor | -| Conditions.cs:49:16:49:16 | [b (line 46): true] access to parameter x | Conditions.cs:49:16:49:18 | [b (line 46): true] ...-- | semmle.label | successor | -| Conditions.cs:49:16:49:16 | access to parameter x | Conditions.cs:49:16:49:18 | ...-- | semmle.label | successor | -| Conditions.cs:49:16:49:18 | ...-- | Conditions.cs:49:22:49:22 | 0 | semmle.label | successor | -| Conditions.cs:49:16:49:18 | [b (line 46): false] ...-- | Conditions.cs:49:22:49:22 | [b (line 46): false] 0 | semmle.label | successor | -| Conditions.cs:49:16:49:18 | [b (line 46): true] ...-- | Conditions.cs:49:22:49:22 | [b (line 46): true] 0 | semmle.label | successor | -| Conditions.cs:49:16:49:22 | ... > ... | Conditions.cs:50:9:53:9 | {...} | semmle.label | true | -| Conditions.cs:49:16:49:22 | ... > ... | Conditions.cs:54:16:54:16 | access to local variable y | semmle.label | false | -| Conditions.cs:49:16:49:22 | [b (line 46): false] ... > ... | Conditions.cs:50:9:53:9 | [b (line 46): false] {...} | semmle.label | true | -| Conditions.cs:49:16:49:22 | [b (line 46): false] ... > ... | Conditions.cs:54:16:54:16 | access to local variable y | semmle.label | false | -| Conditions.cs:49:16:49:22 | [b (line 46): true] ... > ... | Conditions.cs:50:9:53:9 | [b (line 46): true] {...} | semmle.label | true | -| Conditions.cs:49:16:49:22 | [b (line 46): true] ... > ... | Conditions.cs:54:16:54:16 | access to local variable y | semmle.label | false | -| Conditions.cs:49:22:49:22 | 0 | Conditions.cs:49:16:49:22 | ... > ... | semmle.label | successor | -| Conditions.cs:49:22:49:22 | [b (line 46): false] 0 | Conditions.cs:49:16:49:22 | [b (line 46): false] ... > ... | semmle.label | successor | -| Conditions.cs:49:22:49:22 | [b (line 46): true] 0 | Conditions.cs:49:16:49:22 | [b (line 46): true] ... > ... | semmle.label | successor | -| Conditions.cs:50:9:53:9 | [b (line 46): false] {...} | Conditions.cs:51:13:52:20 | [b (line 46): false] if (...) ... | semmle.label | successor | -| Conditions.cs:50:9:53:9 | [b (line 46): true] {...} | Conditions.cs:51:13:52:20 | [b (line 46): true] if (...) ... | semmle.label | successor | -| Conditions.cs:50:9:53:9 | {...} | Conditions.cs:51:13:52:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:51:13:52:20 | [b (line 46): false] if (...) ... | Conditions.cs:51:17:51:17 | [b (line 46): false] access to parameter b | semmle.label | successor | -| Conditions.cs:51:13:52:20 | [b (line 46): true] if (...) ... | Conditions.cs:51:17:51:17 | [b (line 46): true] access to parameter b | semmle.label | successor | -| Conditions.cs:51:13:52:20 | if (...) ... | Conditions.cs:51:17:51:17 | access to parameter b | semmle.label | successor | -| Conditions.cs:51:17:51:17 | [b (line 46): false] access to parameter b | Conditions.cs:49:16:49:16 | [b (line 46): false] access to parameter x | semmle.label | false | -| Conditions.cs:51:17:51:17 | [b (line 46): true] access to parameter b | Conditions.cs:52:17:52:20 | [b (line 46): true] ...; | semmle.label | true | -| Conditions.cs:51:17:51:17 | access to parameter b | Conditions.cs:49:16:49:16 | [b (line 46): false] access to parameter x | semmle.label | false | -| Conditions.cs:51:17:51:17 | access to parameter b | Conditions.cs:52:17:52:20 | [b (line 46): true] ...; | semmle.label | true | -| Conditions.cs:52:17:52:17 | [b (line 46): true] access to local variable y | Conditions.cs:52:17:52:19 | [b (line 46): true] ...++ | semmle.label | successor | -| Conditions.cs:52:17:52:19 | [b (line 46): true] ...++ | Conditions.cs:49:16:49:16 | [b (line 46): true] access to parameter x | semmle.label | successor | -| Conditions.cs:52:17:52:20 | [b (line 46): true] ...; | Conditions.cs:52:17:52:17 | [b (line 46): true] access to local variable y | semmle.label | successor | -| Conditions.cs:54:9:54:17 | return ...; | Conditions.cs:46:9:46:10 | exit M4 (normal) | semmle.label | return | -| Conditions.cs:54:16:54:16 | access to local variable y | Conditions.cs:54:9:54:17 | return ...; | semmle.label | successor | -| Conditions.cs:57:9:57:10 | enter M5 | Conditions.cs:58:5:68:5 | {...} | semmle.label | successor | -| Conditions.cs:57:9:57:10 | exit M5 (normal) | Conditions.cs:57:9:57:10 | exit M5 | semmle.label | successor | -| Conditions.cs:58:5:68:5 | {...} | Conditions.cs:59:9:59:18 | ... ...; | semmle.label | successor | -| Conditions.cs:59:9:59:18 | ... ...; | Conditions.cs:59:17:59:17 | 0 | semmle.label | successor | -| Conditions.cs:59:13:59:17 | Int32 y = ... | Conditions.cs:60:9:64:9 | while (...) ... | semmle.label | successor | -| Conditions.cs:59:17:59:17 | 0 | Conditions.cs:59:13:59:17 | Int32 y = ... | semmle.label | successor | -| Conditions.cs:60:9:64:9 | while (...) ... | Conditions.cs:60:16:60:16 | access to parameter x | semmle.label | successor | -| Conditions.cs:60:16:60:16 | [b (line 57): false] access to parameter x | Conditions.cs:60:16:60:18 | [b (line 57): false] ...-- | semmle.label | successor | -| Conditions.cs:60:16:60:16 | [b (line 57): true] access to parameter x | Conditions.cs:60:16:60:18 | [b (line 57): true] ...-- | semmle.label | successor | -| Conditions.cs:60:16:60:16 | access to parameter x | Conditions.cs:60:16:60:18 | ...-- | semmle.label | successor | -| Conditions.cs:60:16:60:18 | ...-- | Conditions.cs:60:22:60:22 | 0 | semmle.label | successor | -| Conditions.cs:60:16:60:18 | [b (line 57): false] ...-- | Conditions.cs:60:22:60:22 | [b (line 57): false] 0 | semmle.label | successor | -| Conditions.cs:60:16:60:18 | [b (line 57): true] ...-- | Conditions.cs:60:22:60:22 | [b (line 57): true] 0 | semmle.label | successor | -| Conditions.cs:60:16:60:22 | ... > ... | Conditions.cs:61:9:64:9 | {...} | semmle.label | true | -| Conditions.cs:60:16:60:22 | ... > ... | Conditions.cs:65:9:66:16 | if (...) ... | semmle.label | false | -| Conditions.cs:60:16:60:22 | [b (line 57): false] ... > ... | Conditions.cs:61:9:64:9 | [b (line 57): false] {...} | semmle.label | true | -| Conditions.cs:60:16:60:22 | [b (line 57): false] ... > ... | Conditions.cs:65:9:66:16 | [b (line 57): false] if (...) ... | semmle.label | false | -| Conditions.cs:60:16:60:22 | [b (line 57): true] ... > ... | Conditions.cs:61:9:64:9 | [b (line 57): true] {...} | semmle.label | true | -| Conditions.cs:60:16:60:22 | [b (line 57): true] ... > ... | Conditions.cs:65:9:66:16 | [b (line 57): true] if (...) ... | semmle.label | false | -| Conditions.cs:60:22:60:22 | 0 | Conditions.cs:60:16:60:22 | ... > ... | semmle.label | successor | -| Conditions.cs:60:22:60:22 | [b (line 57): false] 0 | Conditions.cs:60:16:60:22 | [b (line 57): false] ... > ... | semmle.label | successor | -| Conditions.cs:60:22:60:22 | [b (line 57): true] 0 | Conditions.cs:60:16:60:22 | [b (line 57): true] ... > ... | semmle.label | successor | -| Conditions.cs:61:9:64:9 | [b (line 57): false] {...} | Conditions.cs:62:13:63:20 | [b (line 57): false] if (...) ... | semmle.label | successor | -| Conditions.cs:61:9:64:9 | [b (line 57): true] {...} | Conditions.cs:62:13:63:20 | [b (line 57): true] if (...) ... | semmle.label | successor | -| Conditions.cs:61:9:64:9 | {...} | Conditions.cs:62:13:63:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:62:13:63:20 | [b (line 57): false] if (...) ... | Conditions.cs:62:17:62:17 | [b (line 57): false] access to parameter b | semmle.label | successor | -| Conditions.cs:62:13:63:20 | [b (line 57): true] if (...) ... | Conditions.cs:62:17:62:17 | [b (line 57): true] access to parameter b | semmle.label | successor | -| Conditions.cs:62:13:63:20 | if (...) ... | Conditions.cs:62:17:62:17 | access to parameter b | semmle.label | successor | -| Conditions.cs:62:17:62:17 | [b (line 57): false] access to parameter b | Conditions.cs:60:16:60:16 | [b (line 57): false] access to parameter x | semmle.label | false | -| Conditions.cs:62:17:62:17 | [b (line 57): true] access to parameter b | Conditions.cs:63:17:63:20 | [b (line 57): true] ...; | semmle.label | true | -| Conditions.cs:62:17:62:17 | access to parameter b | Conditions.cs:60:16:60:16 | [b (line 57): false] access to parameter x | semmle.label | false | -| Conditions.cs:62:17:62:17 | access to parameter b | Conditions.cs:63:17:63:20 | [b (line 57): true] ...; | semmle.label | true | -| Conditions.cs:63:17:63:17 | [b (line 57): true] access to local variable y | Conditions.cs:63:17:63:19 | [b (line 57): true] ...++ | semmle.label | successor | -| Conditions.cs:63:17:63:19 | [b (line 57): true] ...++ | Conditions.cs:60:16:60:16 | [b (line 57): true] access to parameter x | semmle.label | successor | -| Conditions.cs:63:17:63:20 | [b (line 57): true] ...; | Conditions.cs:63:17:63:17 | [b (line 57): true] access to local variable y | semmle.label | successor | -| Conditions.cs:65:9:66:16 | [b (line 57): false] if (...) ... | Conditions.cs:65:13:65:13 | [b (line 57): false] access to parameter b | semmle.label | successor | -| Conditions.cs:65:9:66:16 | [b (line 57): true] if (...) ... | Conditions.cs:65:13:65:13 | [b (line 57): true] access to parameter b | semmle.label | successor | -| Conditions.cs:65:9:66:16 | if (...) ... | Conditions.cs:65:13:65:13 | access to parameter b | semmle.label | successor | -| Conditions.cs:65:13:65:13 | [b (line 57): false] access to parameter b | Conditions.cs:67:16:67:16 | access to local variable y | semmle.label | false | -| Conditions.cs:65:13:65:13 | [b (line 57): true] access to parameter b | Conditions.cs:66:13:66:16 | ...; | semmle.label | true | -| Conditions.cs:65:13:65:13 | access to parameter b | Conditions.cs:66:13:66:16 | ...; | semmle.label | true | -| Conditions.cs:65:13:65:13 | access to parameter b | Conditions.cs:67:16:67:16 | access to local variable y | semmle.label | false | -| Conditions.cs:66:13:66:13 | access to local variable y | Conditions.cs:66:13:66:15 | ...++ | semmle.label | successor | -| Conditions.cs:66:13:66:15 | ...++ | Conditions.cs:67:16:67:16 | access to local variable y | semmle.label | successor | -| Conditions.cs:66:13:66:16 | ...; | Conditions.cs:66:13:66:13 | access to local variable y | semmle.label | successor | -| Conditions.cs:67:9:67:17 | return ...; | Conditions.cs:57:9:57:10 | exit M5 (normal) | semmle.label | return | -| Conditions.cs:67:16:67:16 | access to local variable y | Conditions.cs:67:9:67:17 | return ...; | semmle.label | successor | -| Conditions.cs:70:9:70:10 | enter M6 | Conditions.cs:71:5:84:5 | {...} | semmle.label | successor | -| Conditions.cs:70:9:70:10 | exit M6 (normal) | Conditions.cs:70:9:70:10 | exit M6 | semmle.label | successor | -| Conditions.cs:71:5:84:5 | {...} | Conditions.cs:72:9:72:30 | ... ...; | semmle.label | successor | -| Conditions.cs:72:9:72:30 | ... ...; | Conditions.cs:72:17:72:18 | access to parameter ss | semmle.label | successor | -| Conditions.cs:72:13:72:29 | Boolean b = ... | Conditions.cs:73:9:73:18 | ... ...; | semmle.label | successor | -| Conditions.cs:72:17:72:18 | access to parameter ss | Conditions.cs:72:17:72:25 | access to property Length | semmle.label | successor | -| Conditions.cs:72:17:72:25 | access to property Length | Conditions.cs:72:29:72:29 | 0 | semmle.label | successor | -| Conditions.cs:72:17:72:29 | ... > ... | Conditions.cs:72:13:72:29 | Boolean b = ... | semmle.label | successor | -| Conditions.cs:72:29:72:29 | 0 | Conditions.cs:72:17:72:29 | ... > ... | semmle.label | successor | -| Conditions.cs:73:9:73:18 | ... ...; | Conditions.cs:73:17:73:17 | 0 | semmle.label | successor | -| Conditions.cs:73:13:73:17 | Int32 x = ... | Conditions.cs:74:27:74:28 | access to parameter ss | semmle.label | successor | -| Conditions.cs:73:17:73:17 | 0 | Conditions.cs:73:13:73:17 | Int32 x = ... | semmle.label | successor | -| Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | Conditions.cs:74:22:74:22 | String _ | semmle.label | non-empty | -| Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | Conditions.cs:81:9:82:16 | if (...) ... | semmle.label | empty | -| Conditions.cs:74:22:74:22 | String _ | Conditions.cs:75:9:80:9 | {...} | semmle.label | successor | -| Conditions.cs:74:27:74:28 | access to parameter ss | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | semmle.label | successor | -| Conditions.cs:75:9:80:9 | {...} | Conditions.cs:76:13:77:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:76:13:77:20 | if (...) ... | Conditions.cs:76:17:76:17 | access to local variable b | semmle.label | successor | -| Conditions.cs:76:17:76:17 | access to local variable b | Conditions.cs:77:17:77:20 | ...; | semmle.label | true | -| Conditions.cs:76:17:76:17 | access to local variable b | Conditions.cs:78:13:79:26 | if (...) ... | semmle.label | false | -| Conditions.cs:77:17:77:17 | access to local variable x | Conditions.cs:77:17:77:19 | ...++ | semmle.label | successor | -| Conditions.cs:77:17:77:19 | ...++ | Conditions.cs:78:13:79:26 | if (...) ... | semmle.label | successor | -| Conditions.cs:77:17:77:20 | ...; | Conditions.cs:77:17:77:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:78:13:79:26 | if (...) ... | Conditions.cs:78:17:78:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:78:17:78:17 | access to local variable x | Conditions.cs:78:21:78:21 | 0 | semmle.label | successor | -| Conditions.cs:78:17:78:21 | ... > ... | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | semmle.label | false | -| Conditions.cs:78:17:78:21 | ... > ... | Conditions.cs:79:17:79:26 | ...; | semmle.label | true | -| Conditions.cs:78:21:78:21 | 0 | Conditions.cs:78:17:78:21 | ... > ... | semmle.label | successor | -| Conditions.cs:79:17:79:25 | ... = ... | Conditions.cs:74:9:80:9 | foreach (... ... in ...) ... | semmle.label | successor | -| Conditions.cs:79:17:79:26 | ...; | Conditions.cs:79:21:79:25 | false | semmle.label | successor | -| Conditions.cs:79:21:79:25 | false | Conditions.cs:79:17:79:25 | ... = ... | semmle.label | successor | -| Conditions.cs:81:9:82:16 | if (...) ... | Conditions.cs:81:13:81:13 | access to local variable b | semmle.label | successor | -| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:82:13:82:16 | ...; | semmle.label | true | -| Conditions.cs:81:13:81:13 | access to local variable b | Conditions.cs:83:16:83:16 | access to local variable x | semmle.label | false | -| Conditions.cs:82:13:82:13 | access to local variable x | Conditions.cs:82:13:82:15 | ...++ | semmle.label | successor | -| Conditions.cs:82:13:82:15 | ...++ | Conditions.cs:83:16:83:16 | access to local variable x | semmle.label | successor | -| Conditions.cs:82:13:82:16 | ...; | Conditions.cs:82:13:82:13 | access to local variable x | semmle.label | successor | -| Conditions.cs:83:9:83:17 | return ...; | Conditions.cs:70:9:70:10 | exit M6 (normal) | semmle.label | return | -| Conditions.cs:83:16:83:16 | access to local variable x | Conditions.cs:83:9:83:17 | return ...; | semmle.label | successor | -| Conditions.cs:86:9:86:10 | enter M7 | Conditions.cs:87:5:100:5 | {...} | semmle.label | successor | -| Conditions.cs:86:9:86:10 | exit M7 (normal) | Conditions.cs:86:9:86:10 | exit M7 | semmle.label | successor | -| Conditions.cs:87:5:100:5 | {...} | Conditions.cs:88:9:88:30 | ... ...; | semmle.label | successor | -| Conditions.cs:88:9:88:30 | ... ...; | Conditions.cs:88:17:88:18 | access to parameter ss | semmle.label | successor | -| Conditions.cs:88:13:88:29 | Boolean b = ... | Conditions.cs:89:9:89:18 | ... ...; | semmle.label | successor | -| Conditions.cs:88:17:88:18 | access to parameter ss | Conditions.cs:88:17:88:25 | access to property Length | semmle.label | successor | -| Conditions.cs:88:17:88:25 | access to property Length | Conditions.cs:88:29:88:29 | 0 | semmle.label | successor | -| Conditions.cs:88:17:88:29 | ... > ... | Conditions.cs:88:13:88:29 | Boolean b = ... | semmle.label | successor | -| Conditions.cs:88:29:88:29 | 0 | Conditions.cs:88:17:88:29 | ... > ... | semmle.label | successor | -| Conditions.cs:89:9:89:18 | ... ...; | Conditions.cs:89:17:89:17 | 0 | semmle.label | successor | -| Conditions.cs:89:13:89:17 | Int32 x = ... | Conditions.cs:90:27:90:28 | access to parameter ss | semmle.label | successor | -| Conditions.cs:89:17:89:17 | 0 | Conditions.cs:89:13:89:17 | Int32 x = ... | semmle.label | successor | -| Conditions.cs:90:9:98:9 | foreach (... ... in ...) ... | Conditions.cs:90:22:90:22 | String _ | semmle.label | non-empty | -| Conditions.cs:90:9:98:9 | foreach (... ... in ...) ... | Conditions.cs:99:16:99:16 | access to local variable x | semmle.label | empty | -| Conditions.cs:90:22:90:22 | String _ | Conditions.cs:91:9:98:9 | {...} | semmle.label | successor | -| Conditions.cs:90:27:90:28 | access to parameter ss | Conditions.cs:90:9:98:9 | foreach (... ... in ...) ... | semmle.label | successor | -| Conditions.cs:91:9:98:9 | {...} | Conditions.cs:92:13:93:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:92:13:93:20 | if (...) ... | Conditions.cs:92:17:92:17 | access to local variable b | semmle.label | successor | -| Conditions.cs:92:17:92:17 | access to local variable b | Conditions.cs:93:17:93:20 | ...; | semmle.label | true | -| Conditions.cs:92:17:92:17 | access to local variable b | Conditions.cs:94:13:95:26 | if (...) ... | semmle.label | false | -| Conditions.cs:93:17:93:17 | access to local variable x | Conditions.cs:93:17:93:19 | ...++ | semmle.label | successor | -| Conditions.cs:93:17:93:19 | ...++ | Conditions.cs:94:13:95:26 | if (...) ... | semmle.label | successor | -| Conditions.cs:93:17:93:20 | ...; | Conditions.cs:93:17:93:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:94:13:95:26 | if (...) ... | Conditions.cs:94:17:94:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:94:17:94:17 | access to local variable x | Conditions.cs:94:21:94:21 | 0 | semmle.label | successor | -| Conditions.cs:94:17:94:21 | ... > ... | Conditions.cs:95:17:95:26 | ...; | semmle.label | true | -| Conditions.cs:94:17:94:21 | ... > ... | Conditions.cs:96:13:97:20 | if (...) ... | semmle.label | false | -| Conditions.cs:94:21:94:21 | 0 | Conditions.cs:94:17:94:21 | ... > ... | semmle.label | successor | -| Conditions.cs:95:17:95:25 | ... = ... | Conditions.cs:96:13:97:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:95:17:95:26 | ...; | Conditions.cs:95:21:95:25 | false | semmle.label | successor | -| Conditions.cs:95:21:95:25 | false | Conditions.cs:95:17:95:25 | ... = ... | semmle.label | successor | -| Conditions.cs:96:13:97:20 | if (...) ... | Conditions.cs:96:17:96:17 | access to local variable b | semmle.label | successor | -| Conditions.cs:96:17:96:17 | access to local variable b | Conditions.cs:90:9:98:9 | foreach (... ... in ...) ... | semmle.label | false | -| Conditions.cs:96:17:96:17 | access to local variable b | Conditions.cs:97:17:97:20 | ...; | semmle.label | true | -| Conditions.cs:97:17:97:17 | access to local variable x | Conditions.cs:97:17:97:19 | ...++ | semmle.label | successor | -| Conditions.cs:97:17:97:19 | ...++ | Conditions.cs:90:9:98:9 | foreach (... ... in ...) ... | semmle.label | successor | -| Conditions.cs:97:17:97:20 | ...; | Conditions.cs:97:17:97:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:99:9:99:17 | return ...; | Conditions.cs:86:9:86:10 | exit M7 (normal) | semmle.label | return | -| Conditions.cs:99:16:99:16 | access to local variable x | Conditions.cs:99:9:99:17 | return ...; | semmle.label | successor | -| Conditions.cs:102:12:102:13 | enter M8 | Conditions.cs:103:5:111:5 | {...} | semmle.label | successor | -| Conditions.cs:102:12:102:13 | exit M8 (normal) | Conditions.cs:102:12:102:13 | exit M8 | semmle.label | successor | -| Conditions.cs:103:5:111:5 | {...} | Conditions.cs:104:9:104:29 | ... ...; | semmle.label | successor | -| Conditions.cs:104:9:104:29 | ... ...; | Conditions.cs:104:17:104:17 | access to parameter b | semmle.label | successor | -| Conditions.cs:104:13:104:28 | String x = ... | Conditions.cs:105:9:106:20 | if (...) ... | semmle.label | successor | -| Conditions.cs:104:17:104:17 | access to parameter b | Conditions.cs:104:17:104:28 | call to method ToString | semmle.label | successor | -| Conditions.cs:104:17:104:28 | call to method ToString | Conditions.cs:104:13:104:28 | String x = ... | semmle.label | successor | -| Conditions.cs:105:9:106:20 | if (...) ... | Conditions.cs:105:13:105:13 | access to parameter b | semmle.label | successor | -| Conditions.cs:105:13:105:13 | access to parameter b | Conditions.cs:106:13:106:20 | [b (line 102): true] ...; | semmle.label | true | -| Conditions.cs:105:13:105:13 | access to parameter b | Conditions.cs:107:9:109:24 | [b (line 102): false] if (...) ... | semmle.label | false | -| Conditions.cs:106:13:106:13 | [b (line 102): true] access to local variable x | Conditions.cs:106:18:106:19 | [b (line 102): true] "" | semmle.label | successor | -| Conditions.cs:106:13:106:19 | [b (line 102): true] ... + ... | Conditions.cs:106:13:106:19 | [b (line 102): true] ... = ... | semmle.label | successor | -| Conditions.cs:106:13:106:19 | [b (line 102): true] ... = ... | Conditions.cs:107:9:109:24 | [b (line 102): true] if (...) ... | semmle.label | successor | -| Conditions.cs:106:13:106:20 | [b (line 102): true] ...; | Conditions.cs:106:13:106:13 | [b (line 102): true] access to local variable x | semmle.label | successor | -| Conditions.cs:106:18:106:19 | [b (line 102): true] "" | Conditions.cs:106:13:106:19 | [b (line 102): true] ... + ... | semmle.label | successor | -| Conditions.cs:107:9:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:107:13:107:13 | [b (line 102): false] access to local variable x | semmle.label | successor | -| Conditions.cs:107:9:109:24 | [b (line 102): true] if (...) ... | Conditions.cs:107:13:107:13 | [b (line 102): true] access to local variable x | semmle.label | successor | -| Conditions.cs:107:13:107:13 | [b (line 102): false] access to local variable x | Conditions.cs:107:13:107:20 | [b (line 102): false] access to property Length | semmle.label | successor | -| Conditions.cs:107:13:107:13 | [b (line 102): true] access to local variable x | Conditions.cs:107:13:107:20 | [b (line 102): true] access to property Length | semmle.label | successor | -| Conditions.cs:107:13:107:20 | [b (line 102): false] access to property Length | Conditions.cs:107:24:107:24 | [b (line 102): false] 0 | semmle.label | successor | -| Conditions.cs:107:13:107:20 | [b (line 102): true] access to property Length | Conditions.cs:107:24:107:24 | [b (line 102): true] 0 | semmle.label | successor | -| Conditions.cs:107:13:107:24 | [b (line 102): false] ... > ... | Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | semmle.label | true | -| Conditions.cs:107:13:107:24 | [b (line 102): false] ... > ... | Conditions.cs:110:16:110:16 | access to local variable x | semmle.label | false | -| Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | semmle.label | true | -| Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | Conditions.cs:110:16:110:16 | access to local variable x | semmle.label | false | -| Conditions.cs:107:24:107:24 | [b (line 102): false] 0 | Conditions.cs:107:13:107:24 | [b (line 102): false] ... > ... | semmle.label | successor | -| Conditions.cs:107:24:107:24 | [b (line 102): true] 0 | Conditions.cs:107:13:107:24 | [b (line 102): true] ... > ... | semmle.label | successor | -| Conditions.cs:108:13:109:24 | [b (line 102): false] if (...) ... | Conditions.cs:108:18:108:18 | [b (line 102): false] access to parameter b | semmle.label | successor | -| Conditions.cs:108:13:109:24 | [b (line 102): true] if (...) ... | Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | semmle.label | successor | -| Conditions.cs:108:17:108:18 | [false] !... | Conditions.cs:110:16:110:16 | access to local variable x | semmle.label | false | -| Conditions.cs:108:17:108:18 | [true] !... | Conditions.cs:109:17:109:24 | ...; | semmle.label | true | -| Conditions.cs:108:18:108:18 | [b (line 102): false] access to parameter b | Conditions.cs:108:17:108:18 | [true] !... | semmle.label | false | -| Conditions.cs:108:18:108:18 | [b (line 102): true] access to parameter b | Conditions.cs:108:17:108:18 | [false] !... | semmle.label | true | -| Conditions.cs:109:17:109:17 | access to local variable x | Conditions.cs:109:22:109:23 | "" | semmle.label | successor | -| Conditions.cs:109:17:109:23 | ... + ... | Conditions.cs:109:17:109:23 | ... = ... | semmle.label | successor | -| Conditions.cs:109:17:109:23 | ... = ... | Conditions.cs:110:16:110:16 | access to local variable x | semmle.label | successor | -| Conditions.cs:109:17:109:24 | ...; | Conditions.cs:109:17:109:17 | access to local variable x | semmle.label | successor | -| Conditions.cs:109:22:109:23 | "" | Conditions.cs:109:17:109:23 | ... + ... | semmle.label | successor | -| Conditions.cs:110:9:110:17 | return ...; | Conditions.cs:102:12:102:13 | exit M8 (normal) | semmle.label | return | -| Conditions.cs:110:16:110:16 | access to local variable x | Conditions.cs:110:9:110:17 | return ...; | semmle.label | successor | -| Conditions.cs:113:10:113:11 | enter M9 | Conditions.cs:114:5:124:5 | {...} | semmle.label | successor | -| Conditions.cs:113:10:113:11 | exit M9 (normal) | Conditions.cs:113:10:113:11 | exit M9 | semmle.label | successor | -| Conditions.cs:114:5:124:5 | {...} | Conditions.cs:115:9:115:24 | ... ...; | semmle.label | successor | -| Conditions.cs:115:9:115:24 | ... ...; | Conditions.cs:115:20:115:23 | null | semmle.label | successor | -| Conditions.cs:115:16:115:23 | String s = ... | Conditions.cs:116:9:123:9 | for (...;...;...) ... | semmle.label | successor | -| Conditions.cs:115:20:115:23 | null | Conditions.cs:115:16:115:23 | String s = ... | semmle.label | successor | -| Conditions.cs:116:9:123:9 | for (...;...;...) ... | Conditions.cs:116:22:116:22 | 0 | semmle.label | successor | -| Conditions.cs:116:18:116:22 | Int32 i = ... | Conditions.cs:116:25:116:25 | access to local variable i | semmle.label | successor | -| Conditions.cs:116:22:116:22 | 0 | Conditions.cs:116:18:116:22 | Int32 i = ... | semmle.label | successor | -| Conditions.cs:116:25:116:25 | access to local variable i | Conditions.cs:116:29:116:32 | access to parameter args | semmle.label | successor | -| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:113:10:113:11 | exit M9 (normal) | semmle.label | false | -| Conditions.cs:116:25:116:39 | ... < ... | Conditions.cs:117:9:123:9 | {...} | semmle.label | true | -| Conditions.cs:116:29:116:32 | access to parameter args | Conditions.cs:116:29:116:39 | access to property Length | semmle.label | successor | -| Conditions.cs:116:29:116:39 | access to property Length | Conditions.cs:116:25:116:39 | ... < ... | semmle.label | successor | -| Conditions.cs:116:42:116:42 | access to local variable i | Conditions.cs:116:42:116:44 | ...++ | semmle.label | successor | -| Conditions.cs:116:42:116:44 | ...++ | Conditions.cs:116:25:116:25 | access to local variable i | semmle.label | successor | -| Conditions.cs:117:9:123:9 | {...} | Conditions.cs:118:13:118:44 | ... ...; | semmle.label | successor | -| Conditions.cs:118:13:118:44 | ... ...; | Conditions.cs:118:24:118:24 | access to local variable i | semmle.label | successor | -| Conditions.cs:118:17:118:43 | Boolean last = ... | Conditions.cs:119:13:120:23 | if (...) ... | semmle.label | successor | -| Conditions.cs:118:24:118:24 | access to local variable i | Conditions.cs:118:29:118:32 | access to parameter args | semmle.label | successor | -| Conditions.cs:118:24:118:43 | ... == ... | Conditions.cs:118:17:118:43 | Boolean last = ... | semmle.label | successor | -| Conditions.cs:118:29:118:32 | access to parameter args | Conditions.cs:118:29:118:39 | access to property Length | semmle.label | successor | -| Conditions.cs:118:29:118:39 | access to property Length | Conditions.cs:118:43:118:43 | 1 | semmle.label | successor | -| Conditions.cs:118:29:118:43 | ... - ... | Conditions.cs:118:24:118:43 | ... == ... | semmle.label | successor | -| Conditions.cs:118:43:118:43 | 1 | Conditions.cs:118:29:118:43 | ... - ... | semmle.label | successor | -| Conditions.cs:119:13:120:23 | if (...) ... | Conditions.cs:119:18:119:21 | access to local variable last | semmle.label | successor | -| Conditions.cs:119:17:119:21 | [false, last (line 118): true] !... | Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | semmle.label | false | -| Conditions.cs:119:17:119:21 | [true, last (line 118): false] !... | Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | semmle.label | true | -| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:17:119:21 | [false, last (line 118): true] !... | semmle.label | true | -| Conditions.cs:119:18:119:21 | access to local variable last | Conditions.cs:119:17:119:21 | [true, last (line 118): false] !... | semmle.label | false | -| Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | semmle.label | successor | -| Conditions.cs:120:17:120:23 | [last (line 118): false] ...; | Conditions.cs:120:21:120:22 | [last (line 118): false] "" | semmle.label | successor | -| Conditions.cs:120:21:120:22 | [last (line 118): false] "" | Conditions.cs:120:17:120:22 | [last (line 118): false] ... = ... | semmle.label | successor | -| Conditions.cs:121:13:122:25 | [last (line 118): false] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | semmle.label | successor | -| Conditions.cs:121:13:122:25 | [last (line 118): true] if (...) ... | Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | semmle.label | successor | -| Conditions.cs:121:17:121:20 | [last (line 118): false] access to local variable last | Conditions.cs:116:42:116:42 | access to local variable i | semmle.label | false | -| Conditions.cs:121:17:121:20 | [last (line 118): true] access to local variable last | Conditions.cs:122:17:122:25 | ...; | semmle.label | true | -| Conditions.cs:122:17:122:24 | ... = ... | Conditions.cs:116:42:116:42 | access to local variable i | semmle.label | successor | -| Conditions.cs:122:17:122:25 | ...; | Conditions.cs:122:21:122:24 | null | semmle.label | successor | -| Conditions.cs:122:21:122:24 | null | Conditions.cs:122:17:122:24 | ... = ... | semmle.label | successor | -| Conditions.cs:129:10:129:12 | enter M10 | Conditions.cs:130:5:141:5 | {...} | semmle.label | successor | -| Conditions.cs:130:5:141:5 | {...} | Conditions.cs:131:9:140:9 | while (...) ... | semmle.label | successor | -| Conditions.cs:131:9:140:9 | while (...) ... | Conditions.cs:131:16:131:19 | true | semmle.label | successor | -| Conditions.cs:131:16:131:19 | [Field1 (line 129): false] true | Conditions.cs:132:9:140:9 | [Field1 (line 129): false] {...} | semmle.label | true | -| Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | Conditions.cs:132:9:140:9 | [Field1 (line 129): true, Field2 (line 129): false] {...} | semmle.label | true | -| Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): true] true | Conditions.cs:132:9:140:9 | [Field1 (line 129): true, Field2 (line 129): true] {...} | semmle.label | true | -| Conditions.cs:131:16:131:19 | true | Conditions.cs:132:9:140:9 | {...} | semmle.label | true | -| Conditions.cs:132:9:140:9 | [Field1 (line 129): false] {...} | Conditions.cs:133:13:139:13 | [Field1 (line 129): false] if (...) ... | semmle.label | successor | -| Conditions.cs:132:9:140:9 | [Field1 (line 129): true, Field2 (line 129): false] {...} | Conditions.cs:133:13:139:13 | [Field1 (line 129): true, Field2 (line 129): false] if (...) ... | semmle.label | successor | -| Conditions.cs:132:9:140:9 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:133:13:139:13 | [Field1 (line 129): true, Field2 (line 129): true] if (...) ... | semmle.label | successor | -| Conditions.cs:132:9:140:9 | {...} | Conditions.cs:133:13:139:13 | if (...) ... | semmle.label | successor | -| Conditions.cs:133:13:139:13 | [Field1 (line 129): false] if (...) ... | Conditions.cs:133:17:133:22 | [Field1 (line 129): false] this access | semmle.label | successor | -| Conditions.cs:133:13:139:13 | [Field1 (line 129): true, Field2 (line 129): false] if (...) ... | Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): false] this access | semmle.label | successor | -| Conditions.cs:133:13:139:13 | [Field1 (line 129): true, Field2 (line 129): true] if (...) ... | Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): true] this access | semmle.label | successor | -| Conditions.cs:133:13:139:13 | if (...) ... | Conditions.cs:133:17:133:22 | this access | semmle.label | successor | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): false] access to field Field1 | Conditions.cs:131:16:131:19 | [Field1 (line 129): false] true | semmle.label | false | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): false] this access | Conditions.cs:133:17:133:22 | [Field1 (line 129): false] access to field Field1 | semmle.label | successor | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): false] access to field Field1 | Conditions.cs:134:13:139:13 | [Field1 (line 129): true, Field2 (line 129): false] {...} | semmle.label | true | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): false] this access | Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): false] access to field Field1 | semmle.label | successor | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | Conditions.cs:134:13:139:13 | [Field1 (line 129): true, Field2 (line 129): true] {...} | semmle.label | true | -| Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:133:17:133:22 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | semmle.label | successor | -| Conditions.cs:133:17:133:22 | access to field Field1 | Conditions.cs:131:16:131:19 | [Field1 (line 129): false] true | semmle.label | false | -| Conditions.cs:133:17:133:22 | access to field Field1 | Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | semmle.label | true | -| Conditions.cs:133:17:133:22 | this access | Conditions.cs:133:17:133:22 | access to field Field1 | semmle.label | successor | -| Conditions.cs:134:13:139:13 | [Field1 (line 129): true, Field2 (line 129): false] {...} | Conditions.cs:135:17:138:17 | [Field1 (line 129): true, Field2 (line 129): false] if (...) ... | semmle.label | successor | -| Conditions.cs:134:13:139:13 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:135:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] if (...) ... | semmle.label | successor | -| Conditions.cs:134:13:139:13 | [Field1 (line 129): true] {...} | Conditions.cs:135:17:138:17 | [Field1 (line 129): true] if (...) ... | semmle.label | successor | -| Conditions.cs:135:17:138:17 | [Field1 (line 129): true, Field2 (line 129): false] if (...) ... | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): false] this access | semmle.label | successor | -| Conditions.cs:135:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] if (...) ... | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | semmle.label | successor | -| Conditions.cs:135:17:138:17 | [Field1 (line 129): true] if (...) ... | Conditions.cs:135:21:135:26 | [Field1 (line 129): true] this access | semmle.label | successor | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): false] access to field Field2 | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | semmle.label | false | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): false] this access | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): false] access to field Field2 | semmle.label | successor | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | semmle.label | true | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:135:21:135:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 | semmle.label | successor | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): false] true | semmle.label | false | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | semmle.label | true | -| Conditions.cs:135:21:135:26 | [Field1 (line 129): true] this access | Conditions.cs:135:21:135:26 | [Field1 (line 129): true] access to field Field2 | semmle.label | successor | -| Conditions.cs:136:17:138:17 | [Field1 (line 129): true, Field2 (line 129): true] {...} | Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | semmle.label | successor | -| Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | semmle.label | successor | -| Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 | semmle.label | successor | -| Conditions.cs:137:21:137:37 | [Field1 (line 129): true, Field2 (line 129): true] call to method ToString | Conditions.cs:131:16:131:19 | [Field1 (line 129): true, Field2 (line 129): true] true | semmle.label | successor | -| Conditions.cs:137:21:137:38 | [Field1 (line 129): true, Field2 (line 129): true] ...; | Conditions.cs:137:21:137:26 | [Field1 (line 129): true, Field2 (line 129): true] this access | semmle.label | successor | -| Conditions.cs:143:10:143:12 | enter M11 | Conditions.cs:144:5:150:5 | {...} | semmle.label | successor | -| Conditions.cs:143:10:143:12 | exit M11 (normal) | Conditions.cs:143:10:143:12 | exit M11 | semmle.label | successor | -| Conditions.cs:144:5:150:5 | {...} | Conditions.cs:145:9:145:30 | ... ...; | semmle.label | successor | -| Conditions.cs:145:9:145:30 | ... ...; | Conditions.cs:145:17:145:17 | access to parameter b | semmle.label | successor | -| Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | semmle.label | successor | -| Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | semmle.label | successor | -| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | semmle.label | true | -| Conditions.cs:145:17:145:17 | access to parameter b | Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | semmle.label | false | -| Conditions.cs:145:17:145:29 | [b (line 143): false] ... ? ... : ... | Conditions.cs:145:13:145:29 | [b (line 143): false] String s = ... | semmle.label | successor | -| Conditions.cs:145:17:145:29 | [b (line 143): true] ... ? ... : ... | Conditions.cs:145:13:145:29 | [b (line 143): true] String s = ... | semmle.label | successor | -| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:145:17:145:29 | [b (line 143): true] ... ? ... : ... | semmle.label | successor | -| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:145:17:145:29 | [b (line 143): false] ... ? ... : ... | semmle.label | successor | -| Conditions.cs:146:9:149:49 | [b (line 143): false] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | semmle.label | successor | -| Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | semmle.label | successor | -| Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | Conditions.cs:149:13:149:49 | ...; | semmle.label | false | -| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:147:13:147:49 | ...; | semmle.label | true | -| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | exit M11 (normal) | semmle.label | successor | -| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:40:147:43 | "a = " | semmle.label | successor | -| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:13:147:48 | call to method WriteLine | semmle.label | successor | -| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:45:147:45 | access to local variable s | semmle.label | successor | -| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:38:147:47 | $"..." | semmle.label | successor | -| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | exit M11 (normal) | semmle.label | successor | -| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:40:149:43 | "b = " | semmle.label | successor | -| 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: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 (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: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: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 | -| 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 | -| Extensions.cs:7:9:7:30 | return ...; | Extensions.cs:5:23:5:29 | exit ToInt32 (normal) | semmle.label | return | -| Extensions.cs:7:16:7:29 | call to method Parse | Extensions.cs:7:9:7:30 | return ...; | semmle.label | successor | -| Extensions.cs:7:28:7:28 | access to parameter s | Extensions.cs:7:16:7:29 | call to method Parse | semmle.label | successor | -| Extensions.cs:10:24:10:29 | enter ToBool | Extensions.cs:11:5:13:5 | {...} | semmle.label | successor | -| Extensions.cs:10:24:10:29 | exit ToBool (normal) | Extensions.cs:10:24:10:29 | exit ToBool | semmle.label | successor | -| Extensions.cs:11:5:13:5 | {...} | Extensions.cs:12:16:12:16 | access to parameter f | semmle.label | successor | -| Extensions.cs:12:9:12:20 | return ...; | Extensions.cs:10:24:10:29 | exit ToBool (normal) | semmle.label | return | -| Extensions.cs:12:16:12:16 | access to parameter f | Extensions.cs:12:18:12:18 | access to parameter s | semmle.label | successor | -| Extensions.cs:12:16:12:19 | delegate call | Extensions.cs:12:9:12:20 | return ...; | semmle.label | successor | -| Extensions.cs:12:18:12:18 | access to parameter s | Extensions.cs:12:16:12:19 | delegate call | semmle.label | successor | -| Extensions.cs:15:23:15:33 | enter CallToInt32 | Extensions.cs:15:48:15:50 | "0" | semmle.label | successor | -| Extensions.cs:15:23:15:33 | exit CallToInt32 (normal) | Extensions.cs:15:23:15:33 | exit CallToInt32 | semmle.label | successor | -| Extensions.cs:15:40:15:51 | call to method ToInt32 | Extensions.cs:15:23:15:33 | exit CallToInt32 (normal) | semmle.label | successor | -| Extensions.cs:15:48:15:50 | "0" | Extensions.cs:15:40:15:51 | call to method ToInt32 | semmle.label | successor | -| Extensions.cs:20:17:20:20 | enter Main | Extensions.cs:21:5:26:5 | {...} | semmle.label | successor | -| Extensions.cs:20:17:20:20 | exit Main (normal) | Extensions.cs:20:17:20:20 | exit Main | semmle.label | successor | -| Extensions.cs:21:5:26:5 | {...} | Extensions.cs:22:9:22:20 | ...; | semmle.label | successor | -| Extensions.cs:22:9:22:9 | access to parameter s | Extensions.cs:22:9:22:19 | call to method ToInt32 | semmle.label | successor | -| Extensions.cs:22:9:22:19 | call to method ToInt32 | Extensions.cs:23:9:23:31 | ...; | semmle.label | successor | -| Extensions.cs:22:9:22:20 | ...; | Extensions.cs:22:9:22:9 | access to parameter s | semmle.label | successor | -| Extensions.cs:23:9:23:30 | call to method ToInt32 | Extensions.cs:24:9:24:46 | ...; | semmle.label | successor | -| Extensions.cs:23:9:23:31 | ...; | Extensions.cs:23:28:23:29 | "" | semmle.label | successor | -| Extensions.cs:23:28:23:29 | "" | Extensions.cs:23:9:23:30 | call to method ToInt32 | semmle.label | successor | -| Extensions.cs:24:9:24:45 | call to method ToBool | Extensions.cs:25:9:25:34 | ...; | semmle.label | successor | -| Extensions.cs:24:9:24:46 | ...; | Extensions.cs:24:27:24:32 | "true" | semmle.label | successor | -| Extensions.cs:24:27:24:32 | "true" | Extensions.cs:24:35:24:44 | access to method Parse | semmle.label | successor | -| Extensions.cs:24:35:24:44 | access to method Parse | Extensions.cs:24:35:24:44 | delegate creation of type Func | semmle.label | successor | -| Extensions.cs:24:35:24:44 | delegate creation of type Func | Extensions.cs:24:9:24:45 | call to method ToBool | semmle.label | successor | -| Extensions.cs:25:9:25:14 | "true" | Extensions.cs:25:23:25:32 | access to method Parse | semmle.label | successor | -| Extensions.cs:25:9:25:33 | call to method ToBool | Extensions.cs:20:17:20:20 | exit Main (normal) | semmle.label | successor | -| Extensions.cs:25:9:25:34 | ...; | Extensions.cs:25:9:25:14 | "true" | semmle.label | successor | -| Extensions.cs:25:23:25:32 | access to method Parse | Extensions.cs:25:23:25:32 | delegate creation of type Func | semmle.label | successor | -| Extensions.cs:25:23:25:32 | delegate creation of type Func | Extensions.cs:25:9:25:33 | call to method ToBool | semmle.label | successor | -| Finally.cs:7:10:7:11 | enter M1 | Finally.cs:8:5:17:5 | {...} | semmle.label | successor | -| Finally.cs:7:10:7:11 | exit M1 (abnormal) | Finally.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| Finally.cs:7:10:7:11 | exit M1 (normal) | Finally.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| Finally.cs:8:5:17:5 | {...} | Finally.cs:9:9:16:9 | try {...} ... | semmle.label | successor | -| Finally.cs:9:9:16:9 | try {...} ... | Finally.cs:10:9:12:9 | {...} | semmle.label | successor | -| Finally.cs:10:9:12:9 | {...} | Finally.cs:11:13:11:38 | ...; | semmle.label | successor | -| Finally.cs:11:13:11:37 | call to method WriteLine | Finally.cs:14:9:16:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| 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: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.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 | 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: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: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 | -| Finally.cs:20:5:52:5 | {...} | Finally.cs:21:9:51:9 | try {...} ... | semmle.label | successor | -| Finally.cs:21:9:51:9 | try {...} ... | Finally.cs:22:9:25:9 | {...} | semmle.label | successor | -| Finally.cs:22:9:25:9 | {...} | Finally.cs:23:13:23:38 | ...; | semmle.label | successor | -| Finally.cs:23:13:23:37 | call to method WriteLine | Finally.cs:24:13:24:19 | return ...; | semmle.label | successor | -| 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: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: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: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 | -| Finally.cs:33:13:35:13 | {...} | Finally.cs:34:17:34:32 | if (...) ... | semmle.label | successor | -| Finally.cs:34:17:34:32 | if (...) ... | Finally.cs:34:21:34:24 | true | semmle.label | successor | -| Finally.cs:34:21:34:24 | true | Finally.cs:34:27:34:32 | throw ...; | semmle.label | true | -| Finally.cs:34:27:34:32 | throw ...; | Finally.cs:37:13:39:13 | [finally: exception(ArgumentException)] {...} | semmle.label | exception(ArgumentException) | -| Finally.cs:37:13:39:13 | [finally: exception(ArgumentException)] {...} | Finally.cs:38:37:38:42 | [finally: exception(ArgumentException)] "Boo!" | semmle.label | successor | -| Finally.cs:38:17:38:44 | [finally: exception(ArgumentException)] throw ...; | Finally.cs:49:9:51:9 | [finally: exception(Exception)] {...} | semmle.label | 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 ...; | 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: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 | -| Finally.cs:49:9:51:9 | [finally: return] {...} | Finally.cs:50:13:50:41 | [finally: return] ...; | semmle.label | successor | -| Finally.cs:49:9:51:9 | {...} | Finally.cs:50:13:50:41 | ...; | semmle.label | successor | -| Finally.cs:50:13:50:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:19:10:19:11 | exit M2 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:50:13:50:40 | [finally: exception(IOException)] call to method WriteLine | Finally.cs:19:10:19:11 | exit M2 (abnormal) | semmle.label | exception(IOException) | -| Finally.cs:50:13:50:40 | [finally: return] call to method WriteLine | Finally.cs:19:10:19:11 | exit M2 (normal) | semmle.label | return | -| Finally.cs:50:13:50:40 | call to method WriteLine | Finally.cs:19:10:19:11 | exit M2 (normal) | semmle.label | successor | -| Finally.cs:50:13:50:41 | ...; | Finally.cs:50:31:50:39 | "Finally" | semmle.label | successor | -| Finally.cs:50:13:50:41 | [finally: exception(Exception)] ...; | Finally.cs:50:31:50:39 | [finally: exception(Exception)] "Finally" | semmle.label | successor | -| Finally.cs:50:13:50:41 | [finally: exception(IOException)] ...; | Finally.cs:50:31:50:39 | [finally: exception(IOException)] "Finally" | semmle.label | successor | -| Finally.cs:50:13:50:41 | [finally: return] ...; | Finally.cs:50:31:50:39 | [finally: return] "Finally" | semmle.label | successor | -| Finally.cs:50:31:50:39 | "Finally" | Finally.cs:50:13:50:40 | call to method WriteLine | semmle.label | successor | -| Finally.cs:50:31:50:39 | [finally: exception(Exception)] "Finally" | Finally.cs:50:13:50:40 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:50:31:50:39 | [finally: exception(IOException)] "Finally" | Finally.cs:50:13:50:40 | [finally: exception(IOException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:50:31:50:39 | [finally: return] "Finally" | Finally.cs:50:13:50:40 | [finally: return] call to method WriteLine | semmle.label | successor | -| Finally.cs:54:10:54:11 | enter M3 | Finally.cs:55:5:72:5 | {...} | semmle.label | successor | -| Finally.cs:54:10:54:11 | exit M3 (abnormal) | Finally.cs:54:10:54:11 | exit M3 | semmle.label | successor | -| Finally.cs:54:10:54:11 | exit M3 (normal) | Finally.cs:54:10:54:11 | exit M3 | semmle.label | successor | -| Finally.cs:55:5:72:5 | {...} | Finally.cs:56:9:71:9 | try {...} ... | semmle.label | successor | -| Finally.cs:56:9:71:9 | try {...} ... | Finally.cs:57:9:60:9 | {...} | semmle.label | successor | -| Finally.cs:57:9:60:9 | {...} | Finally.cs:58:13:58:38 | ...; | semmle.label | successor | -| Finally.cs:58:13:58:37 | call to method WriteLine | Finally.cs:59:13:59:19 | return ...; | semmle.label | successor | -| 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: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: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: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: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:43 | [exception: Exception] access to property Message | Finally.cs:65:48:65:51 | [exception: Exception] 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:48:65:51 | [exception: Exception] null | Finally.cs:65:35:65:51 | [exception: Exception] ... != ... | 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: 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: 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: 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: 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 | -| Finally.cs:74:10:74:11 | exit M4 (normal) | Finally.cs:74:10:74:11 | exit M4 | semmle.label | successor | -| Finally.cs:75:5:101:5 | {...} | Finally.cs:76:9:76:19 | ... ...; | semmle.label | successor | -| Finally.cs:76:9:76:19 | ... ...; | Finally.cs:76:17:76:18 | 10 | semmle.label | successor | -| Finally.cs:76:13:76:18 | Int32 i = ... | Finally.cs:77:9:100:9 | while (...) ... | semmle.label | successor | -| Finally.cs:76:17:76:18 | 10 | Finally.cs:76:13:76:18 | Int32 i = ... | semmle.label | successor | -| Finally.cs:77:9:100:9 | while (...) ... | Finally.cs:77:16:77:16 | access to local variable i | semmle.label | successor | -| Finally.cs:77:16:77:16 | access to local variable i | Finally.cs:77:20:77:20 | 0 | semmle.label | successor | -| Finally.cs:77:16:77:20 | ... > ... | Finally.cs:74:10:74:11 | exit M4 (normal) | semmle.label | false | -| Finally.cs:77:16:77:20 | ... > ... | Finally.cs:78:9:100:9 | {...} | semmle.label | true | -| Finally.cs:77:20:77:20 | 0 | Finally.cs:77:16:77:20 | ... > ... | semmle.label | successor | -| Finally.cs:78:9:100:9 | {...} | Finally.cs:79:13:99:13 | try {...} ... | semmle.label | successor | -| Finally.cs:79:13:99:13 | try {...} ... | Finally.cs:80:13:87:13 | {...} | semmle.label | successor | -| Finally.cs:80:13:87:13 | {...} | Finally.cs:81:17:82:27 | if (...) ... | semmle.label | successor | -| Finally.cs:81:17:82:27 | if (...) ... | Finally.cs:81:21:81:21 | access to local variable i | semmle.label | successor | -| Finally.cs:81:21:81:21 | access to local variable i | Finally.cs:81:26:81:26 | 0 | semmle.label | successor | -| Finally.cs:81:21:81:26 | ... == ... | Finally.cs:82:21:82:27 | return ...; | semmle.label | true | -| Finally.cs:81:21:81:26 | ... == ... | Finally.cs:83:17:84:29 | if (...) ... | semmle.label | false | -| Finally.cs:81:26:81:26 | 0 | Finally.cs:81:21:81:26 | ... == ... | semmle.label | successor | -| Finally.cs:82:21:82:27 | return ...; | Finally.cs:89:13:99:13 | [finally: return] {...} | semmle.label | return | -| Finally.cs:83:17:84:29 | if (...) ... | Finally.cs:83:21:83:21 | access to local variable i | semmle.label | successor | -| Finally.cs:83:21:83:21 | access to local variable i | Finally.cs:83:26:83:26 | 1 | semmle.label | successor | -| Finally.cs:83:21:83:26 | ... == ... | Finally.cs:84:21:84:29 | continue; | semmle.label | true | -| Finally.cs:83:21:83:26 | ... == ... | Finally.cs:85:17:86:26 | if (...) ... | semmle.label | false | -| Finally.cs:83:26:83:26 | 1 | Finally.cs:83:21:83:26 | ... == ... | semmle.label | successor | -| Finally.cs:84:21:84:29 | continue; | Finally.cs:89:13:99:13 | [finally: continue] {...} | semmle.label | continue | -| Finally.cs:85:17:86:26 | if (...) ... | Finally.cs:85:21:85:21 | access to local variable i | semmle.label | successor | -| Finally.cs:85:21:85:21 | access to local variable i | Finally.cs:85:26:85:26 | 2 | semmle.label | successor | -| Finally.cs:85:21:85:26 | ... == ... | Finally.cs:86:21:86:26 | break; | semmle.label | true | -| Finally.cs:85:21:85:26 | ... == ... | Finally.cs:89:13:99:13 | {...} | semmle.label | false | -| Finally.cs:85:26:85:26 | 2 | Finally.cs:85:21:85:26 | ... == ... | semmle.label | successor | -| Finally.cs:86:21:86:26 | break; | Finally.cs:89:13:99:13 | [finally: break] {...} | semmle.label | break | -| Finally.cs:89:13:99:13 | [finally: break] {...} | Finally.cs:90:17:98:17 | [finally: break] try {...} ... | semmle.label | successor | -| Finally.cs:89:13:99:13 | [finally: continue] {...} | Finally.cs:90:17:98:17 | [finally: continue] try {...} ... | semmle.label | successor | -| Finally.cs:89:13:99:13 | [finally: return] {...} | Finally.cs:90:17:98:17 | [finally: return] try {...} ... | semmle.label | successor | -| Finally.cs:89:13:99:13 | {...} | Finally.cs:90:17:98:17 | try {...} ... | semmle.label | successor | -| Finally.cs:90:17:98:17 | [finally: break] try {...} ... | Finally.cs:91:17:94:17 | [finally: break] {...} | semmle.label | successor | -| Finally.cs:90:17:98:17 | [finally: continue] try {...} ... | Finally.cs:91:17:94:17 | [finally: continue] {...} | semmle.label | successor | -| Finally.cs:90:17:98:17 | [finally: return] try {...} ... | Finally.cs:91:17:94:17 | [finally: return] {...} | semmle.label | successor | -| Finally.cs:90:17:98:17 | try {...} ... | Finally.cs:91:17:94:17 | {...} | semmle.label | successor | -| Finally.cs:91:17:94:17 | [finally: break] {...} | Finally.cs:92:21:93:46 | [finally: break] if (...) ... | semmle.label | successor | -| Finally.cs:91:17:94:17 | [finally: continue] {...} | Finally.cs:92:21:93:46 | [finally: continue] if (...) ... | semmle.label | successor | -| Finally.cs:91:17:94:17 | [finally: return] {...} | Finally.cs:92:21:93:46 | [finally: return] if (...) ... | semmle.label | successor | -| Finally.cs:91:17:94:17 | {...} | Finally.cs:92:21:93:46 | if (...) ... | semmle.label | successor | -| Finally.cs:92:21:93:46 | [finally: break] if (...) ... | Finally.cs:92:25:92:25 | [finally: break] access to local variable i | semmle.label | successor | -| Finally.cs:92:21:93:46 | [finally: continue] if (...) ... | Finally.cs:92:25:92:25 | [finally: continue] access to local variable i | semmle.label | successor | -| Finally.cs:92:21:93:46 | [finally: return] if (...) ... | Finally.cs:92:25:92:25 | [finally: return] access to local variable i | semmle.label | successor | -| Finally.cs:92:21:93:46 | if (...) ... | Finally.cs:92:25:92:25 | access to local variable i | semmle.label | successor | -| Finally.cs:92:25:92:25 | [finally: break] access to local variable i | Finally.cs:92:30:92:30 | [finally: break] 3 | semmle.label | successor | -| Finally.cs:92:25:92:25 | [finally: continue] access to local variable i | Finally.cs:92:30:92:30 | [finally: continue] 3 | semmle.label | successor | -| Finally.cs:92:25:92:25 | [finally: return] access to local variable i | Finally.cs:92:30:92:30 | [finally: return] 3 | semmle.label | successor | -| Finally.cs:92:25:92:25 | access to local variable i | Finally.cs:92:30:92:30 | 3 | semmle.label | successor | -| Finally.cs:92:25:92:30 | ... == ... | Finally.cs:93:31:93:45 | object creation of type Exception | semmle.label | true | -| Finally.cs:92:25:92:30 | ... == ... | Finally.cs:96:17:98:17 | {...} | semmle.label | false | -| Finally.cs:92:25:92:30 | [finally: break] ... == ... | Finally.cs:93:31:93:45 | [finally: break] object creation of type Exception | semmle.label | true | -| Finally.cs:92:25:92:30 | [finally: break] ... == ... | Finally.cs:96:17:98:17 | [finally: break] {...} | semmle.label | false | -| Finally.cs:92:25:92:30 | [finally: continue] ... == ... | Finally.cs:93:31:93:45 | [finally: continue] object creation of type Exception | semmle.label | true | -| Finally.cs:92:25:92:30 | [finally: continue] ... == ... | Finally.cs:96:17:98:17 | [finally: continue] {...} | semmle.label | false | -| Finally.cs:92:25:92:30 | [finally: return] ... == ... | Finally.cs:93:31:93:45 | [finally: return] object creation of type Exception | semmle.label | true | -| Finally.cs:92:25:92:30 | [finally: return] ... == ... | Finally.cs:96:17:98:17 | [finally: return] {...} | semmle.label | false | -| Finally.cs:92:30:92:30 | 3 | Finally.cs:92:25:92:30 | ... == ... | semmle.label | successor | -| 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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 | -| Finally.cs:103:10:103:11 | exit M5 (normal) | Finally.cs:103:10:103:11 | exit M5 | semmle.label | successor | -| Finally.cs:104:5:119:5 | {...} | Finally.cs:105:9:118:9 | try {...} ... | semmle.label | successor | -| Finally.cs:105:9:118:9 | try {...} ... | Finally.cs:106:9:111:9 | {...} | semmle.label | successor | -| Finally.cs:106:9:111:9 | {...} | Finally.cs:107:13:108:23 | if (...) ... | semmle.label | successor | -| Finally.cs:107:13:108:23 | if (...) ... | Finally.cs:107:17:107:21 | this access | semmle.label | successor | -| Finally.cs:107:17:107:21 | access to field Field | Finally.cs:107:17:107:28 | access to property Length | semmle.label | successor | -| Finally.cs:107:17:107:21 | access to field Field | Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:107:17:107:21 | this access | Finally.cs:107:17:107:21 | access to field Field | semmle.label | successor | -| Finally.cs:107:17:107:28 | access to property Length | Finally.cs:107:33:107:33 | 0 | semmle.label | successor | -| Finally.cs:107:17:107:28 | access to property Length | Finally.cs:113:9:118:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:107:17:107:28 | access to property Length | Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:107:17:107:33 | ... == ... | Finally.cs:108:17:108:23 | return ...; | semmle.label | true | -| Finally.cs:107:17:107:33 | ... == ... | Finally.cs:109:13:110:49 | if (...) ... | semmle.label | false | -| Finally.cs:107:33:107:33 | 0 | Finally.cs:107:17:107:33 | ... == ... | semmle.label | successor | -| Finally.cs:108:17:108:23 | return ...; | Finally.cs:113:9:118:9 | [finally: return] {...} | semmle.label | return | -| Finally.cs:109:13:110:49 | if (...) ... | Finally.cs:109:17:109:21 | this access | semmle.label | successor | -| Finally.cs:109:17:109:21 | access to field Field | Finally.cs:109:17:109:28 | access to property Length | semmle.label | successor | -| Finally.cs:109:17:109:21 | access to field Field | Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:109:17:109:21 | this access | Finally.cs:109:17:109:21 | access to field Field | semmle.label | successor | -| Finally.cs:109:17:109:28 | access to property Length | Finally.cs:109:33:109:33 | 1 | semmle.label | successor | -| Finally.cs:109:17:109:28 | access to property Length | Finally.cs:113:9:118:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:109:17:109:28 | access to property Length | Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:109:17:109:33 | ... == ... | Finally.cs:110:23:110:48 | object creation of type OutOfMemoryException | semmle.label | true | -| Finally.cs:109:17:109:33 | ... == ... | Finally.cs:113:9:118:9 | {...} | semmle.label | false | -| Finally.cs:109:33:109:33 | 1 | Finally.cs:109:17:109:33 | ... == ... | semmle.label | successor | -| Finally.cs:110:17:110:49 | throw ...; | Finally.cs:113:9:118:9 | [finally: exception(OutOfMemoryException)] {...} | semmle.label | exception(OutOfMemoryException) | -| Finally.cs:110:23:110:48 | object creation of type OutOfMemoryException | Finally.cs:110:17:110:49 | throw ...; | semmle.label | successor | -| Finally.cs:110:23:110:48 | object creation of type OutOfMemoryException | Finally.cs:113:9:118:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:113:9:118:9 | [finally: exception(Exception)] {...} | Finally.cs:114:13:115:41 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:113:9:118:9 | [finally: exception(NullReferenceException)] {...} | Finally.cs:114:13:115:41 | [finally: exception(NullReferenceException)] if (...) ... | semmle.label | successor | -| Finally.cs:113:9:118:9 | [finally: exception(OutOfMemoryException)] {...} | Finally.cs:114:13:115:41 | [finally: exception(OutOfMemoryException)] if (...) ... | semmle.label | successor | -| Finally.cs:113:9:118:9 | [finally: return] {...} | Finally.cs:114:13:115:41 | [finally: return] if (...) ... | semmle.label | successor | -| Finally.cs:113:9:118:9 | {...} | Finally.cs:114:13:115:41 | if (...) ... | semmle.label | successor | -| Finally.cs:114:13:115:41 | [finally: exception(Exception)] if (...) ... | Finally.cs:114:19:114:23 | [finally: exception(Exception)] this access | semmle.label | successor | -| Finally.cs:114:13:115:41 | [finally: exception(NullReferenceException)] if (...) ... | Finally.cs:114:19:114:23 | [finally: exception(NullReferenceException)] this access | semmle.label | successor | -| Finally.cs:114:13:115:41 | [finally: exception(OutOfMemoryException)] if (...) ... | Finally.cs:114:19:114:23 | [finally: exception(OutOfMemoryException)] this access | semmle.label | successor | -| Finally.cs:114:13:115:41 | [finally: return] if (...) ... | Finally.cs:114:19:114:23 | [finally: return] this access | semmle.label | successor | -| Finally.cs:114:13:115:41 | if (...) ... | Finally.cs:114:19:114:23 | this access | semmle.label | successor | -| Finally.cs:114:17:114:36 | [false, finally: exception(Exception)] !... | Finally.cs:116:13:117:37 | [finally: exception(Exception)] if (...) ... | semmle.label | false | -| Finally.cs:114:17:114:36 | [false, finally: exception(NullReferenceException)] !... | Finally.cs:116:13:117:37 | [finally: exception(NullReferenceException)] if (...) ... | semmle.label | false | -| Finally.cs:114:17:114:36 | [false, finally: exception(OutOfMemoryException)] !... | Finally.cs:116:13:117:37 | [finally: exception(OutOfMemoryException)] if (...) ... | semmle.label | false | -| Finally.cs:114:17:114:36 | [false, finally: return] !... | Finally.cs:116:13:117:37 | [finally: return] if (...) ... | semmle.label | false | -| Finally.cs:114:17:114:36 | [false] !... | Finally.cs:116:13:117:37 | if (...) ... | semmle.label | false | -| Finally.cs:114:17:114:36 | [true, finally: exception(Exception)] !... | Finally.cs:115:17:115:41 | [finally: exception(Exception)] ...; | semmle.label | true | -| Finally.cs:114:17:114:36 | [true, finally: exception(NullReferenceException)] !... | Finally.cs:115:17:115:41 | [finally: exception(NullReferenceException)] ...; | semmle.label | true | -| Finally.cs:114:17:114:36 | [true, finally: exception(OutOfMemoryException)] !... | Finally.cs:115:17:115:41 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | true | -| Finally.cs:114:17:114:36 | [true, finally: return] !... | Finally.cs:115:17:115:41 | [finally: return] ...; | semmle.label | true | -| Finally.cs:114:17:114:36 | [true] !... | Finally.cs:115:17:115:41 | ...; | semmle.label | true | -| Finally.cs:114:19:114:23 | [finally: exception(Exception)] access to field Field | Finally.cs:114:19:114:30 | [finally: exception(Exception)] access to property Length | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: exception(Exception)] this access | Finally.cs:114:19:114:23 | [finally: exception(Exception)] access to field Field | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: exception(NullReferenceException)] access to field Field | Finally.cs:114:19:114:30 | [finally: exception(NullReferenceException)] access to property Length | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: exception(NullReferenceException)] this access | Finally.cs:114:19:114:23 | [finally: exception(NullReferenceException)] access to field Field | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: exception(OutOfMemoryException)] access to field Field | Finally.cs:114:19:114:30 | [finally: exception(OutOfMemoryException)] access to property Length | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: exception(OutOfMemoryException)] this access | Finally.cs:114:19:114:23 | [finally: exception(OutOfMemoryException)] access to field Field | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: return] access to field Field | Finally.cs:114:19:114:30 | [finally: return] access to property Length | semmle.label | successor | -| Finally.cs:114:19:114:23 | [finally: return] this access | Finally.cs:114:19:114:23 | [finally: return] access to field Field | semmle.label | successor | -| Finally.cs:114:19:114:23 | access to field Field | Finally.cs:114:19:114:30 | access to property Length | semmle.label | successor | -| Finally.cs:114:19:114:23 | this access | Finally.cs:114:19:114:23 | access to field Field | semmle.label | successor | -| Finally.cs:114:19:114:30 | [finally: exception(Exception)] access to property Length | Finally.cs:114:35:114:35 | [finally: exception(Exception)] 0 | semmle.label | successor | -| Finally.cs:114:19:114:30 | [finally: exception(NullReferenceException)] access to property Length | Finally.cs:114:35:114:35 | [finally: exception(NullReferenceException)] 0 | semmle.label | successor | -| Finally.cs:114:19:114:30 | [finally: exception(OutOfMemoryException)] access to property Length | Finally.cs:114:35:114:35 | [finally: exception(OutOfMemoryException)] 0 | semmle.label | successor | -| Finally.cs:114:19:114:30 | [finally: return] access to property Length | Finally.cs:114:35:114:35 | [finally: return] 0 | semmle.label | successor | -| Finally.cs:114:19:114:30 | access to property Length | Finally.cs:114:35:114:35 | 0 | semmle.label | successor | -| Finally.cs:114:19:114:35 | ... == ... | Finally.cs:114:17:114:36 | [false] !... | semmle.label | true | -| Finally.cs:114:19:114:35 | ... == ... | Finally.cs:114:17:114:36 | [true] !... | semmle.label | false | -| Finally.cs:114:19:114:35 | [finally: exception(Exception)] ... == ... | Finally.cs:114:17:114:36 | [false, finally: exception(Exception)] !... | semmle.label | true | -| Finally.cs:114:19:114:35 | [finally: exception(Exception)] ... == ... | Finally.cs:114:17:114:36 | [true, finally: exception(Exception)] !... | semmle.label | false | -| Finally.cs:114:19:114:35 | [finally: exception(NullReferenceException)] ... == ... | Finally.cs:114:17:114:36 | [false, finally: exception(NullReferenceException)] !... | semmle.label | true | -| Finally.cs:114:19:114:35 | [finally: exception(NullReferenceException)] ... == ... | Finally.cs:114:17:114:36 | [true, finally: exception(NullReferenceException)] !... | semmle.label | false | -| Finally.cs:114:19:114:35 | [finally: exception(OutOfMemoryException)] ... == ... | Finally.cs:114:17:114:36 | [false, finally: exception(OutOfMemoryException)] !... | semmle.label | true | -| Finally.cs:114:19:114:35 | [finally: exception(OutOfMemoryException)] ... == ... | Finally.cs:114:17:114:36 | [true, finally: exception(OutOfMemoryException)] !... | semmle.label | false | -| Finally.cs:114:19:114:35 | [finally: return] ... == ... | Finally.cs:114:17:114:36 | [false, finally: return] !... | semmle.label | true | -| Finally.cs:114:19:114:35 | [finally: return] ... == ... | Finally.cs:114:17:114:36 | [true, finally: return] !... | semmle.label | false | -| Finally.cs:114:35:114:35 | 0 | Finally.cs:114:19:114:35 | ... == ... | semmle.label | successor | -| Finally.cs:114:35:114:35 | [finally: exception(Exception)] 0 | Finally.cs:114:19:114:35 | [finally: exception(Exception)] ... == ... | semmle.label | successor | -| Finally.cs:114:35:114:35 | [finally: exception(NullReferenceException)] 0 | Finally.cs:114:19:114:35 | [finally: exception(NullReferenceException)] ... == ... | semmle.label | successor | -| Finally.cs:114:35:114:35 | [finally: exception(OutOfMemoryException)] 0 | Finally.cs:114:19:114:35 | [finally: exception(OutOfMemoryException)] ... == ... | semmle.label | successor | -| Finally.cs:114:35:114:35 | [finally: return] 0 | Finally.cs:114:19:114:35 | [finally: return] ... == ... | semmle.label | successor | -| Finally.cs:115:17:115:40 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:116:13:117:37 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:115:17:115:40 | [finally: exception(NullReferenceException)] call to method WriteLine | Finally.cs:116:13:117:37 | [finally: exception(NullReferenceException)] if (...) ... | semmle.label | successor | -| Finally.cs:115:17:115:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:116:13:117:37 | [finally: exception(OutOfMemoryException)] if (...) ... | semmle.label | successor | -| Finally.cs:115:17:115:40 | [finally: return] call to method WriteLine | Finally.cs:116:13:117:37 | [finally: return] if (...) ... | semmle.label | successor | -| Finally.cs:115:17:115:40 | call to method WriteLine | Finally.cs:116:13:117:37 | if (...) ... | semmle.label | successor | -| Finally.cs:115:17:115:41 | ...; | Finally.cs:115:35:115:39 | this access | semmle.label | successor | -| Finally.cs:115:17:115:41 | [finally: exception(Exception)] ...; | Finally.cs:115:35:115:39 | [finally: exception(Exception)] this access | semmle.label | successor | -| Finally.cs:115:17:115:41 | [finally: exception(NullReferenceException)] ...; | Finally.cs:115:35:115:39 | [finally: exception(NullReferenceException)] this access | semmle.label | successor | -| Finally.cs:115:17:115:41 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:115:35:115:39 | [finally: exception(OutOfMemoryException)] this access | semmle.label | successor | -| Finally.cs:115:17:115:41 | [finally: return] ...; | Finally.cs:115:35:115:39 | [finally: return] this access | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(Exception)] access to field Field | Finally.cs:115:17:115:40 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(Exception)] this access | Finally.cs:115:35:115:39 | [finally: exception(Exception)] access to field Field | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(NullReferenceException)] access to field Field | Finally.cs:115:17:115:40 | [finally: exception(NullReferenceException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(NullReferenceException)] this access | Finally.cs:115:35:115:39 | [finally: exception(NullReferenceException)] access to field Field | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(OutOfMemoryException)] access to field Field | Finally.cs:115:17:115:40 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: exception(OutOfMemoryException)] this access | Finally.cs:115:35:115:39 | [finally: exception(OutOfMemoryException)] access to field Field | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: return] access to field Field | Finally.cs:115:17:115:40 | [finally: return] call to method WriteLine | semmle.label | successor | -| Finally.cs:115:35:115:39 | [finally: return] this access | Finally.cs:115:35:115:39 | [finally: return] access to field Field | semmle.label | successor | -| Finally.cs:115:35:115:39 | access to field Field | Finally.cs:115:17:115:40 | call to method WriteLine | semmle.label | successor | -| Finally.cs:115:35:115:39 | this access | Finally.cs:115:35:115:39 | access to field Field | semmle.label | successor | -| Finally.cs:116:13:117:37 | [finally: exception(Exception)] if (...) ... | Finally.cs:116:17:116:21 | [finally: exception(Exception)] this access | semmle.label | successor | -| Finally.cs:116:13:117:37 | [finally: exception(NullReferenceException)] if (...) ... | Finally.cs:116:17:116:21 | [finally: exception(NullReferenceException)] this access | semmle.label | successor | -| Finally.cs:116:13:117:37 | [finally: exception(OutOfMemoryException)] if (...) ... | Finally.cs:116:17:116:21 | [finally: exception(OutOfMemoryException)] this access | semmle.label | successor | -| Finally.cs:116:13:117:37 | [finally: return] if (...) ... | Finally.cs:116:17:116:21 | [finally: return] this access | semmle.label | successor | -| Finally.cs:116:13:117:37 | if (...) ... | Finally.cs:116:17:116:21 | this access | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(Exception)] access to field Field | Finally.cs:116:17:116:28 | [finally: exception(Exception)] access to property Length | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(Exception)] this access | Finally.cs:116:17:116:21 | [finally: exception(Exception)] access to field Field | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(NullReferenceException)] access to field Field | Finally.cs:116:17:116:28 | [finally: exception(NullReferenceException)] access to property Length | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(NullReferenceException)] this access | Finally.cs:116:17:116:21 | [finally: exception(NullReferenceException)] access to field Field | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(OutOfMemoryException)] access to field Field | Finally.cs:116:17:116:28 | [finally: exception(OutOfMemoryException)] access to property Length | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: exception(OutOfMemoryException)] this access | Finally.cs:116:17:116:21 | [finally: exception(OutOfMemoryException)] access to field Field | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: return] access to field Field | Finally.cs:116:17:116:28 | [finally: return] access to property Length | semmle.label | successor | -| Finally.cs:116:17:116:21 | [finally: return] this access | Finally.cs:116:17:116:21 | [finally: return] access to field Field | semmle.label | successor | -| Finally.cs:116:17:116:21 | access to field Field | Finally.cs:116:17:116:28 | access to property Length | semmle.label | successor | -| Finally.cs:116:17:116:21 | this access | Finally.cs:116:17:116:21 | access to field Field | semmle.label | successor | -| Finally.cs:116:17:116:28 | [finally: exception(Exception)] access to property Length | Finally.cs:116:32:116:32 | [finally: exception(Exception)] 0 | semmle.label | successor | -| Finally.cs:116:17:116:28 | [finally: exception(NullReferenceException)] access to property Length | Finally.cs:116:32:116:32 | [finally: exception(NullReferenceException)] 0 | semmle.label | successor | -| Finally.cs:116:17:116:28 | [finally: exception(OutOfMemoryException)] access to property Length | Finally.cs:116:32:116:32 | [finally: exception(OutOfMemoryException)] 0 | semmle.label | successor | -| Finally.cs:116:17:116:28 | [finally: return] access to property Length | Finally.cs:116:32:116:32 | [finally: return] 0 | semmle.label | successor | -| Finally.cs:116:17:116:28 | access to property Length | Finally.cs:116:32:116:32 | 0 | semmle.label | successor | -| Finally.cs:116:17:116:32 | ... > ... | Finally.cs:103:10:103:11 | exit M5 (normal) | semmle.label | false | -| Finally.cs:116:17:116:32 | ... > ... | Finally.cs:117:17:117:37 | ...; | semmle.label | true | -| Finally.cs:116:17:116:32 | [finally: exception(Exception)] ... > ... | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:116:17:116:32 | [finally: exception(Exception)] ... > ... | Finally.cs:117:17:117:37 | [finally: exception(Exception)] ...; | semmle.label | true | -| Finally.cs:116:17:116:32 | [finally: exception(NullReferenceException)] ... > ... | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(NullReferenceException) | -| Finally.cs:116:17:116:32 | [finally: exception(NullReferenceException)] ... > ... | Finally.cs:117:17:117:37 | [finally: exception(NullReferenceException)] ...; | semmle.label | true | -| Finally.cs:116:17:116:32 | [finally: exception(OutOfMemoryException)] ... > ... | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(OutOfMemoryException) | -| Finally.cs:116:17:116:32 | [finally: exception(OutOfMemoryException)] ... > ... | Finally.cs:117:17:117:37 | [finally: exception(OutOfMemoryException)] ...; | semmle.label | true | -| Finally.cs:116:17:116:32 | [finally: return] ... > ... | Finally.cs:103:10:103:11 | exit M5 (normal) | semmle.label | return | -| Finally.cs:116:17:116:32 | [finally: return] ... > ... | Finally.cs:117:17:117:37 | [finally: return] ...; | semmle.label | true | -| Finally.cs:116:32:116:32 | 0 | Finally.cs:116:17:116:32 | ... > ... | semmle.label | successor | -| Finally.cs:116:32:116:32 | [finally: exception(Exception)] 0 | Finally.cs:116:17:116:32 | [finally: exception(Exception)] ... > ... | semmle.label | successor | -| Finally.cs:116:32:116:32 | [finally: exception(NullReferenceException)] 0 | Finally.cs:116:17:116:32 | [finally: exception(NullReferenceException)] ... > ... | semmle.label | successor | -| Finally.cs:116:32:116:32 | [finally: exception(OutOfMemoryException)] 0 | Finally.cs:116:17:116:32 | [finally: exception(OutOfMemoryException)] ... > ... | semmle.label | successor | -| Finally.cs:116:32:116:32 | [finally: return] 0 | Finally.cs:116:17:116:32 | [finally: return] ... > ... | semmle.label | successor | -| Finally.cs:117:17:117:36 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:117:17:117:36 | [finally: exception(NullReferenceException)] call to method WriteLine | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(NullReferenceException) | -| Finally.cs:117:17:117:36 | [finally: exception(OutOfMemoryException)] call to method WriteLine | Finally.cs:103:10:103:11 | exit M5 (abnormal) | semmle.label | exception(OutOfMemoryException) | -| Finally.cs:117:17:117:36 | [finally: return] call to method WriteLine | Finally.cs:103:10:103:11 | exit M5 (normal) | semmle.label | return | -| Finally.cs:117:17:117:36 | call to method WriteLine | Finally.cs:103:10:103:11 | exit M5 (normal) | semmle.label | successor | -| Finally.cs:117:17:117:37 | ...; | Finally.cs:117:35:117:35 | 1 | semmle.label | successor | -| Finally.cs:117:17:117:37 | [finally: exception(Exception)] ...; | Finally.cs:117:35:117:35 | [finally: exception(Exception)] 1 | semmle.label | successor | -| Finally.cs:117:17:117:37 | [finally: exception(NullReferenceException)] ...; | Finally.cs:117:35:117:35 | [finally: exception(NullReferenceException)] 1 | semmle.label | successor | -| Finally.cs:117:17:117:37 | [finally: exception(OutOfMemoryException)] ...; | Finally.cs:117:35:117:35 | [finally: exception(OutOfMemoryException)] 1 | semmle.label | successor | -| Finally.cs:117:17:117:37 | [finally: return] ...; | Finally.cs:117:35:117:35 | [finally: return] 1 | semmle.label | successor | -| Finally.cs:117:35:117:35 | 1 | Finally.cs:117:17:117:36 | call to method WriteLine | semmle.label | successor | -| Finally.cs:117:35:117:35 | [finally: exception(Exception)] 1 | Finally.cs:117:17:117:36 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:117:35:117:35 | [finally: exception(NullReferenceException)] 1 | Finally.cs:117:17:117:36 | [finally: exception(NullReferenceException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:117:35:117:35 | [finally: exception(OutOfMemoryException)] 1 | Finally.cs:117:17:117:36 | [finally: exception(OutOfMemoryException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:117:35:117:35 | [finally: return] 1 | Finally.cs:117:17:117:36 | [finally: return] call to method WriteLine | semmle.label | successor | -| Finally.cs:121:10:121:11 | enter M6 | Finally.cs:122:5:131:5 | {...} | semmle.label | successor | -| Finally.cs:121:10:121:11 | exit M6 (normal) | Finally.cs:121:10:121:11 | exit M6 | semmle.label | successor | -| Finally.cs:122:5:131:5 | {...} | Finally.cs:123:9:130:9 | try {...} ... | semmle.label | successor | -| Finally.cs:123:9:130:9 | try {...} ... | Finally.cs:124:9:126:9 | {...} | semmle.label | successor | -| Finally.cs:124:9:126:9 | {...} | Finally.cs:125:13:125:41 | ... ...; | semmle.label | successor | -| Finally.cs:125:13:125:41 | ... ...; | Finally.cs:125:24:125:24 | 0 | semmle.label | successor | -| Finally.cs:125:17:125:40 | Double temp = ... | Finally.cs:121:10:121:11 | exit M6 (normal) | semmle.label | successor | -| Finally.cs:125:24:125:24 | 0 | Finally.cs:125:24:125:24 | (...) ... | semmle.label | successor | -| Finally.cs:125:24:125:24 | (...) ... | Finally.cs:125:28:125:40 | access to constant E | semmle.label | successor | -| Finally.cs:125:24:125:40 | ... / ... | Finally.cs:125:17:125:40 | Double temp = ... | semmle.label | successor | -| Finally.cs:125:28:125:40 | access to constant E | Finally.cs:125:24:125:40 | ... / ... | semmle.label | successor | -| Finally.cs:133:10:133:11 | enter M7 | Finally.cs:134:5:145:5 | {...} | semmle.label | successor | -| Finally.cs:133:10:133:11 | exit M7 (abnormal) | Finally.cs:133:10:133:11 | exit M7 | semmle.label | successor | -| Finally.cs:134:5:145:5 | {...} | Finally.cs:135:9:143:9 | try {...} ... | semmle.label | successor | -| Finally.cs:135:9:143:9 | try {...} ... | Finally.cs:136:9:138:9 | {...} | semmle.label | successor | -| Finally.cs:136:9:138:9 | {...} | Finally.cs:137:13:137:37 | ...; | semmle.label | successor | -| Finally.cs:137:13:137:36 | call to method WriteLine | Finally.cs:140:9:143:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| 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: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.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 | 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 | 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: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 | -| Finally.cs:148:5:170:5 | {...} | Finally.cs:149:9:169:9 | try {...} ... | semmle.label | successor | -| Finally.cs:149:9:169:9 | try {...} ... | Finally.cs:150:9:153:9 | {...} | semmle.label | successor | -| Finally.cs:150:9:153:9 | {...} | Finally.cs:151:13:152:50 | if (...) ... | semmle.label | successor | -| Finally.cs:151:13:152:50 | if (...) ... | Finally.cs:151:17:151:20 | access to parameter args | semmle.label | successor | -| Finally.cs:151:17:151:20 | access to parameter args | Finally.cs:151:25:151:28 | null | semmle.label | successor | -| Finally.cs:151:17:151:28 | ... == ... | Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | semmle.label | true | -| Finally.cs:151:17:151:28 | ... == ... | Finally.cs:155:9:169:9 | {...} | semmle.label | false | -| Finally.cs:151:25:151:28 | null | Finally.cs:151:17:151:28 | ... == ... | semmle.label | successor | -| Finally.cs:152:17:152:50 | throw ...; | Finally.cs:155:9:169:9 | [finally: exception(ArgumentNullException)] {...} | semmle.label | exception(ArgumentNullException) | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:152:17:152:50 | throw ...; | semmle.label | successor | -| Finally.cs:152:23:152:49 | object creation of type ArgumentNullException | Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:155:9:169:9 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:156:13:168:13 | [finally: exception(ArgumentNullException)] try {...} ... | semmle.label | successor | -| Finally.cs:155:9:169:9 | [finally: exception(Exception)] {...} | Finally.cs:156:13:168:13 | [finally: exception(Exception)] try {...} ... | semmle.label | successor | -| Finally.cs:155:9:169:9 | {...} | Finally.cs:156:13:168:13 | try {...} ... | semmle.label | successor | -| Finally.cs:156:13:168:13 | [finally: exception(ArgumentNullException)] try {...} ... | Finally.cs:157:13:160:13 | [finally: exception(ArgumentNullException)] {...} | semmle.label | successor | -| Finally.cs:156:13:168:13 | [finally: exception(Exception)] try {...} ... | Finally.cs:157:13:160:13 | [finally: exception(Exception)] {...} | semmle.label | successor | -| Finally.cs:156:13:168:13 | try {...} ... | Finally.cs:157:13:160:13 | {...} | semmle.label | successor | -| Finally.cs:157:13:160:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:158:17:159:45 | [finally: exception(ArgumentNullException)] if (...) ... | semmle.label | successor | -| Finally.cs:157:13:160:13 | [finally: exception(Exception)] {...} | Finally.cs:158:17:159:45 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:157:13:160:13 | {...} | Finally.cs:158:17:159:45 | if (...) ... | semmle.label | successor | -| Finally.cs:158:17:159:45 | [finally: exception(ArgumentNullException)] if (...) ... | Finally.cs:158:21:158:24 | [finally: exception(ArgumentNullException)] access to parameter args | semmle.label | successor | -| Finally.cs:158:17:159:45 | [finally: exception(Exception)] if (...) ... | Finally.cs:158:21:158:24 | [finally: exception(Exception)] access to parameter args | semmle.label | successor | -| Finally.cs:158:17:159:45 | if (...) ... | Finally.cs:158:21:158:24 | access to parameter args | semmle.label | successor | -| Finally.cs:158:21:158:24 | [finally: exception(ArgumentNullException)] access to parameter args | Finally.cs:158:21:158:31 | [finally: exception(ArgumentNullException)] access to property Length | semmle.label | successor | -| Finally.cs:158:21:158:24 | [finally: exception(Exception)] access to parameter args | Finally.cs:158:21:158:31 | [finally: exception(Exception)] access to property Length | semmle.label | successor | -| Finally.cs:158:21:158:24 | access to parameter args | Finally.cs:158:21:158:31 | access to property Length | semmle.label | successor | -| Finally.cs:158:21:158:31 | [finally: exception(ArgumentNullException)] access to property Length | Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | semmle.label | successor | -| Finally.cs:158:21:158:31 | [finally: exception(ArgumentNullException)] access to property Length | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:158:21:158:31 | [finally: exception(ArgumentNullException)] access to property Length | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:158:21:158:31 | [finally: exception(Exception)] access to property Length | Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | semmle.label | successor | -| Finally.cs:158:21:158:31 | [finally: exception(Exception)] access to property Length | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:158:21:158:31 | [finally: exception(Exception)] access to property Length | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:158:21:158:31 | access to property Length | Finally.cs:158:36:158:36 | 1 | semmle.label | successor | -| Finally.cs:158:21:158:31 | access to property Length | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:158:21:158:31 | access to property Length | Finally.cs:161:13:164:13 | [exception: NullReferenceException] catch (...) {...} | semmle.label | exception(NullReferenceException) | -| Finally.cs:158:21:158:36 | ... == ... | Finally.cs:147:10:147:11 | exit M8 (normal) | semmle.label | false | -| Finally.cs:158:21:158:36 | ... == ... | Finally.cs:159:41:159:43 | "1" | semmle.label | true | -| Finally.cs:158:21:158:36 | [finally: exception(ArgumentNullException)] ... == ... | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(ArgumentNullException) | -| Finally.cs:158:21:158:36 | [finally: exception(ArgumentNullException)] ... == ... | Finally.cs:159:41:159:43 | [finally: exception(ArgumentNullException)] "1" | semmle.label | true | -| Finally.cs:158:21:158:36 | [finally: exception(Exception)] ... == ... | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:158:21:158:36 | [finally: exception(Exception)] ... == ... | Finally.cs:159:41:159:43 | [finally: exception(Exception)] "1" | semmle.label | true | -| Finally.cs:158:36:158:36 | 1 | Finally.cs:158:21:158:36 | ... == ... | semmle.label | successor | -| Finally.cs:158:36:158:36 | [finally: exception(ArgumentNullException)] 1 | Finally.cs:158:21:158:36 | [finally: exception(ArgumentNullException)] ... == ... | semmle.label | successor | -| Finally.cs:158:36:158:36 | [finally: exception(Exception)] 1 | Finally.cs:158:21:158:36 | [finally: exception(Exception)] ... == ... | semmle.label | successor | -| Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:159:21:159:45 | [finally: exception(Exception)] throw ...; | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:159:21:159:45 | throw ...; | Finally.cs:161:13:164:13 | [exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:159:21:159:45 | [finally: exception(ArgumentNullException)] throw ...; | semmle.label | successor | -| Finally.cs:159:27:159:44 | [finally: exception(ArgumentNullException)] object creation of type Exception | Finally.cs:161:13:164:13 | [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} | semmle.label | exception(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 ...; | semmle.label | successor | -| Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | Finally.cs:161:13:164:13 | [finally: exception(Exception), exception: Exception] catch (...) {...} | semmle.label | exception(Exception) | -| 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 | [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(Exception)] "1" | Finally.cs:159:27:159:44 | [finally: exception(Exception)] object creation of type Exception | semmle.label | successor | -| 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 | [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(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: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 | [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(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: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 | [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(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: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 | [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(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: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 | [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(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: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 | [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(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: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 | -| Finally.cs:163:17:163:42 | [finally: exception(ArgumentNullException)] call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(ArgumentNullException) | -| Finally.cs:163:17:163:42 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:163:17:163:42 | call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (normal) | semmle.label | successor | -| Finally.cs:163:17:163:43 | ...; | Finally.cs:163:35:163:38 | access to parameter args | semmle.label | successor | -| Finally.cs:163:17:163:43 | [finally: exception(ArgumentNullException)] ...; | Finally.cs:163:35:163:38 | [finally: exception(ArgumentNullException)] access to parameter args | semmle.label | successor | -| Finally.cs:163:17:163:43 | [finally: exception(Exception)] ...; | Finally.cs:163:35:163:38 | [finally: exception(Exception)] access to parameter args | semmle.label | successor | -| Finally.cs:163:35:163:38 | [finally: exception(ArgumentNullException)] access to parameter args | Finally.cs:163:40:163:40 | [finally: exception(ArgumentNullException)] 0 | semmle.label | successor | -| Finally.cs:163:35:163:38 | [finally: exception(Exception)] access to parameter args | Finally.cs:163:40:163:40 | [finally: exception(Exception)] 0 | semmle.label | successor | -| Finally.cs:163:35:163:38 | access to parameter args | Finally.cs:163:40:163:40 | 0 | semmle.label | successor | -| Finally.cs:163:35:163:41 | [finally: exception(ArgumentNullException)] access to array element | Finally.cs:163:17:163:42 | [finally: exception(ArgumentNullException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:163:35:163:41 | [finally: exception(Exception)] access to array element | Finally.cs:163:17:163:42 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:163:35:163:41 | access to array element | Finally.cs:163:17:163:42 | call to method WriteLine | semmle.label | successor | -| Finally.cs:163:40:163:40 | 0 | Finally.cs:163:35:163:41 | access to array element | semmle.label | successor | -| Finally.cs:163:40:163:40 | [finally: exception(ArgumentNullException)] 0 | Finally.cs:163:35:163:41 | [finally: exception(ArgumentNullException)] access to array element | semmle.label | successor | -| Finally.cs:163:40:163:40 | [finally: exception(Exception)] 0 | Finally.cs:163:35:163:41 | [finally: exception(Exception)] access to array element | semmle.label | successor | -| Finally.cs:165:13:168:13 | [finally: exception(ArgumentNullException)] catch {...} | Finally.cs:166:13:168:13 | [finally: exception(ArgumentNullException)] {...} | semmle.label | successor | -| Finally.cs:165:13:168:13 | [finally: exception(Exception)] catch {...} | Finally.cs:166:13:168:13 | [finally: exception(Exception)] {...} | semmle.label | successor | -| Finally.cs:165:13:168:13 | catch {...} | Finally.cs:166:13:168:13 | {...} | semmle.label | successor | -| Finally.cs:166:13:168:13 | [finally: exception(ArgumentNullException)] {...} | Finally.cs:167:17:167:38 | [finally: exception(ArgumentNullException)] ...; | semmle.label | successor | -| Finally.cs:166:13:168:13 | [finally: exception(Exception)] {...} | Finally.cs:167:17:167:38 | [finally: exception(Exception)] ...; | semmle.label | successor | -| Finally.cs:166:13:168:13 | {...} | Finally.cs:167:17:167:38 | ...; | semmle.label | successor | -| Finally.cs:167:17:167:37 | [finally: exception(ArgumentNullException)] call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(ArgumentNullException) | -| Finally.cs:167:17:167:37 | [finally: exception(Exception)] call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:167:17:167:37 | call to method WriteLine | Finally.cs:147:10:147:11 | exit M8 (normal) | semmle.label | successor | -| Finally.cs:167:17:167:38 | ...; | Finally.cs:167:35:167:36 | "" | semmle.label | successor | -| Finally.cs:167:17:167:38 | [finally: exception(ArgumentNullException)] ...; | Finally.cs:167:35:167:36 | [finally: exception(ArgumentNullException)] "" | semmle.label | successor | -| Finally.cs:167:17:167:38 | [finally: exception(Exception)] ...; | Finally.cs:167:35:167:36 | [finally: exception(Exception)] "" | semmle.label | successor | -| Finally.cs:167:35:167:36 | "" | Finally.cs:167:17:167:37 | call to method WriteLine | semmle.label | successor | -| Finally.cs:167:35:167:36 | [finally: exception(ArgumentNullException)] "" | Finally.cs:167:17:167:37 | [finally: exception(ArgumentNullException)] call to method WriteLine | semmle.label | successor | -| Finally.cs:167:35:167:36 | [finally: exception(Exception)] "" | Finally.cs:167:17:167:37 | [finally: exception(Exception)] call to method WriteLine | semmle.label | successor | -| Finally.cs:176:10:176:11 | enter M9 | Finally.cs:177:5:193:5 | {...} | semmle.label | successor | -| Finally.cs:176:10:176:11 | exit M9 (abnormal) | Finally.cs:176:10:176:11 | exit M9 | semmle.label | successor | -| Finally.cs:176:10:176:11 | exit M9 (normal) | Finally.cs:176:10:176:11 | exit M9 | semmle.label | successor | -| Finally.cs:177:5:193:5 | {...} | Finally.cs:178:9:192:9 | try {...} ... | semmle.label | successor | -| Finally.cs:178:9:192:9 | try {...} ... | Finally.cs:179:9:181:9 | {...} | semmle.label | successor | -| Finally.cs:179:9:181:9 | {...} | Finally.cs:180:13:180:43 | if (...) ... | semmle.label | successor | -| Finally.cs:180:13:180:43 | if (...) ... | Finally.cs:180:17:180:18 | access to parameter b1 | semmle.label | successor | -| 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 | semmle.label | true | -| Finally.cs:180:17:180:18 | access to parameter b1 | Finally.cs:183:9:192:9 | [b1 (line 176): false] {...} | semmle.label | false | -| Finally.cs:180:21:180:43 | [b1 (line 176): true] throw ...; | Finally.cs:183:9:192:9 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | semmle.label | exception(ExceptionA) | -| Finally.cs:180:27:180:42 | [b1 (line 176): true] object creation of type ExceptionA | Finally.cs:180:21:180:43 | [b1 (line 176): true] throw ...; | semmle.label | successor | -| Finally.cs:180:27:180:42 | [b1 (line 176): true] object creation of type ExceptionA | Finally.cs:183:9:192:9 | [finally: exception(Exception), b1 (line 176): true] {...} | semmle.label | exception(Exception) | -| Finally.cs:183:9:192:9 | [b1 (line 176): false] {...} | Finally.cs:184:13:191:13 | [b1 (line 176): false] try {...} ... | semmle.label | successor | -| Finally.cs:183:9:192:9 | [finally: exception(Exception), b1 (line 176): true] {...} | Finally.cs:184:13:191:13 | [finally: exception(Exception), b1 (line 176): true] try {...} ... | semmle.label | successor | -| Finally.cs:183:9:192:9 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | Finally.cs:184:13:191:13 | [finally: exception(ExceptionA), b1 (line 176): true] try {...} ... | semmle.label | successor | -| Finally.cs:184:13:191:13 | [b1 (line 176): false] try {...} ... | Finally.cs:185:13:187:13 | [b1 (line 176): false] {...} | semmle.label | successor | -| Finally.cs:184:13:191:13 | [finally: exception(Exception), b1 (line 176): true] try {...} ... | Finally.cs:185:13:187:13 | [finally: exception(Exception), b1 (line 176): true] {...} | semmle.label | successor | -| Finally.cs:184:13:191:13 | [finally: exception(ExceptionA), b1 (line 176): true] try {...} ... | Finally.cs:185:13:187:13 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | semmle.label | successor | -| Finally.cs:185:13:187:13 | [b1 (line 176): false] {...} | Finally.cs:186:17:186:47 | [b1 (line 176): false] if (...) ... | semmle.label | successor | -| Finally.cs:185:13:187:13 | [finally: exception(Exception), b1 (line 176): true] {...} | Finally.cs:186:17:186:47 | [finally: exception(Exception), b1 (line 176): true] if (...) ... | semmle.label | successor | -| Finally.cs:185:13:187:13 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | Finally.cs:186:17:186:47 | [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... | semmle.label | successor | -| Finally.cs:186:17:186:47 | [b1 (line 176): false] if (...) ... | Finally.cs:186:21:186:22 | [b1 (line 176): false] access to parameter b2 | semmle.label | successor | -| Finally.cs:186:17:186:47 | [finally: exception(Exception), b1 (line 176): true] if (...) ... | Finally.cs:186:21:186:22 | [finally: exception(Exception), b1 (line 176): true] access to parameter b2 | semmle.label | successor | -| Finally.cs:186:17:186:47 | [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... | Finally.cs:186:21:186:22 | [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b2 | semmle.label | successor | -| Finally.cs:186:21:186:22 | [b1 (line 176): false] access to parameter b2 | Finally.cs:176:10:176:11 | exit M9 (normal) | semmle.label | false | -| Finally.cs:186:21:186:22 | [b1 (line 176): false] access to parameter b2 | Finally.cs:186:31:186:46 | [b1 (line 176): false, b2 (line 176): true] object creation of type ExceptionB | semmle.label | true | -| Finally.cs:186:21:186:22 | [finally: exception(Exception), b1 (line 176): true] access to parameter b2 | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:186:21:186:22 | [finally: exception(Exception), b1 (line 176): true] access to parameter b2 | Finally.cs:186:31:186:46 | [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | semmle.label | true | -| Finally.cs:186:21:186:22 | [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b2 | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(ExceptionA) | -| Finally.cs:186:21:186:22 | [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b2 | Finally.cs:186:31:186:46 | [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | semmle.label | true | -| Finally.cs:186:25:186:47 | [b1 (line 176): false, b2 (line 176): true] throw ...; | Finally.cs:188:13:191:13 | [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] catch (...) {...} | semmle.label | exception(ExceptionB) | -| Finally.cs:186:25:186:47 | [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] throw ...; | Finally.cs:188:13:191:13 | [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | semmle.label | exception(ExceptionB) | -| Finally.cs:186:25:186:47 | [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] throw ...; | Finally.cs:188:13:191:13 | [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | semmle.label | exception(ExceptionB) | -| Finally.cs:186:31:186:46 | [b1 (line 176): false, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:186:25:186:47 | [b1 (line 176): false, b2 (line 176): true] throw ...; | semmle.label | successor | -| Finally.cs:186:31:186:46 | [b1 (line 176): false, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:188:13:191:13 | [exception: Exception, b1 (line 176): false, b2 (line 176): true] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:186:31:186:46 | [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:186:25:186:47 | [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] throw ...; | semmle.label | successor | -| Finally.cs:186:31:186:46 | [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:188:13:191:13 | [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:186:31:186:46 | [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:186:25:186:47 | [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] throw ...; | semmle.label | successor | -| Finally.cs:186:31:186:46 | [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB | Finally.cs:188:13:191:13 | [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | semmle.label | exception(Exception) | -| Finally.cs:188:13:191:13 | [exception: Exception, b1 (line 176): false, b2 (line 176): true] catch (...) {...} | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:188:13:191:13 | [exception: Exception, b1 (line 176): false, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [exception: Exception, b1 (line 176): false, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:13:191:13 | [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:13:191:13 | [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:188:13:191:13 | [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:13:191:13 | [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:13:191:13 | [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:188:13:191:13 | [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:13:191:13 | [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} | Finally.cs:188:38:188:39 | [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | semmle.label | match | -| Finally.cs:188:38:188:39 | [exception: Exception, b1 (line 176): false, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [b1 (line 176): false] {...} | semmle.label | true | -| Finally.cs:188:38:188:39 | [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [b1 (line 176): false] {...} | semmle.label | true | -| Finally.cs:188:38:188:39 | [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [finally: exception(Exception), b1 (line 176): true] {...} | semmle.label | true | -| Finally.cs:188:38:188:39 | [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [finally: exception(Exception), b1 (line 176): true] {...} | semmle.label | true | -| Finally.cs:188:38:188:39 | [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | semmle.label | true | -| Finally.cs:188:38:188:39 | [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 | Finally.cs:189:13:191:13 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | semmle.label | true | -| Finally.cs:189:13:191:13 | [b1 (line 176): false] {...} | Finally.cs:190:17:190:47 | [b1 (line 176): false] if (...) ... | semmle.label | successor | -| Finally.cs:189:13:191:13 | [finally: exception(Exception), b1 (line 176): true] {...} | Finally.cs:190:17:190:47 | [finally: exception(Exception), b1 (line 176): true] if (...) ... | semmle.label | successor | -| Finally.cs:189:13:191:13 | [finally: exception(ExceptionA), b1 (line 176): true] {...} | Finally.cs:190:17:190:47 | [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... | semmle.label | successor | -| Finally.cs:190:17:190:47 | [b1 (line 176): false] if (...) ... | Finally.cs:190:21:190:22 | [b1 (line 176): false] access to parameter b1 | semmle.label | successor | -| Finally.cs:190:17:190:47 | [finally: exception(Exception), b1 (line 176): true] if (...) ... | Finally.cs:190:21:190:22 | [finally: exception(Exception), b1 (line 176): true] access to parameter b1 | semmle.label | successor | -| Finally.cs:190:17:190:47 | [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... | Finally.cs:190:21:190:22 | [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b1 | semmle.label | successor | -| Finally.cs:190:21:190:22 | [b1 (line 176): false] access to parameter b1 | Finally.cs:176:10:176:11 | exit M9 (normal) | semmle.label | false | -| Finally.cs:190:21:190:22 | [finally: exception(Exception), b1 (line 176): true] access to parameter b1 | Finally.cs:190:31:190:46 | [finally: exception(Exception)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:190:21:190:22 | [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b1 | Finally.cs:190:31:190:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | semmle.label | true | -| Finally.cs:190:25:190:47 | [finally: exception(Exception)] throw ...; | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:190:25:190:47 | [finally: exception(ExceptionA)] throw ...; | Finally.cs:176:10:176:11 | exit M9 (abnormal) | semmle.label | exception(ExceptionC) | -| Finally.cs:190:31:190:46 | [finally: exception(Exception)] object creation of type ExceptionC | Finally.cs:190:25:190:47 | [finally: exception(Exception)] throw ...; | semmle.label | successor | -| Finally.cs:190:31:190:46 | [finally: exception(ExceptionA)] object creation of type ExceptionC | Finally.cs:190:25:190:47 | [finally: exception(ExceptionA)] throw ...; | semmle.label | successor | -| Finally.cs:195:10:195:12 | enter M10 | Finally.cs:196:5:214:5 | {...} | semmle.label | successor | -| Finally.cs:195:10:195:12 | exit M10 (abnormal) | Finally.cs:195:10:195:12 | exit M10 | semmle.label | successor | -| Finally.cs:195:10:195:12 | exit M10 (normal) | Finally.cs:195:10:195:12 | exit M10 | semmle.label | successor | -| Finally.cs:196:5:214:5 | {...} | Finally.cs:197:9:212:9 | try {...} ... | semmle.label | successor | -| Finally.cs:197:9:212:9 | try {...} ... | Finally.cs:198:9:200:9 | {...} | semmle.label | successor | -| Finally.cs:198:9:200:9 | {...} | Finally.cs:199:13:199:43 | if (...) ... | semmle.label | successor | -| Finally.cs:199:13:199:43 | if (...) ... | Finally.cs:199:17:199:18 | access to parameter b1 | semmle.label | successor | -| Finally.cs:199:17:199:18 | access to parameter b1 | Finally.cs:199:27:199:42 | object creation of type ExceptionA | semmle.label | true | -| Finally.cs:199:17:199:18 | access to parameter b1 | Finally.cs:202:9:212:9 | {...} | semmle.label | false | -| Finally.cs:199:21:199:43 | throw ...; | Finally.cs:202:9:212:9 | [finally: exception(ExceptionA)] {...} | semmle.label | exception(ExceptionA) | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:199:21:199:43 | throw ...; | semmle.label | successor | -| Finally.cs:199:27:199:42 | object creation of type ExceptionA | Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | semmle.label | exception(Exception) | -| Finally.cs:202:9:212:9 | [finally: exception(Exception)] {...} | Finally.cs:203:13:210:13 | [finally: exception(Exception)] try {...} ... | semmle.label | successor | -| Finally.cs:202:9:212:9 | [finally: exception(ExceptionA)] {...} | Finally.cs:203:13:210:13 | [finally: exception(ExceptionA)] try {...} ... | semmle.label | successor | -| Finally.cs:202:9:212:9 | {...} | Finally.cs:203:13:210:13 | try {...} ... | semmle.label | successor | -| Finally.cs:203:13:210:13 | [finally: exception(Exception)] try {...} ... | Finally.cs:204:13:206:13 | [finally: exception(Exception)] {...} | semmle.label | successor | -| Finally.cs:203:13:210:13 | [finally: exception(ExceptionA)] try {...} ... | Finally.cs:204:13:206:13 | [finally: exception(ExceptionA)] {...} | semmle.label | successor | -| Finally.cs:203:13:210:13 | try {...} ... | Finally.cs:204:13:206:13 | {...} | semmle.label | successor | -| Finally.cs:204:13:206:13 | [finally: exception(Exception)] {...} | Finally.cs:205:17:205:47 | [finally: exception(Exception)] if (...) ... | semmle.label | successor | -| Finally.cs:204:13:206:13 | [finally: exception(ExceptionA)] {...} | Finally.cs:205:17:205:47 | [finally: exception(ExceptionA)] if (...) ... | semmle.label | successor | -| Finally.cs:204:13:206:13 | {...} | Finally.cs:205:17:205:47 | if (...) ... | semmle.label | successor | -| Finally.cs:205:17:205:47 | [finally: exception(Exception)] if (...) ... | Finally.cs:205:21:205:22 | [finally: exception(Exception)] access to parameter b2 | semmle.label | successor | -| Finally.cs:205:17:205:47 | [finally: exception(ExceptionA)] if (...) ... | Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | semmle.label | successor | -| Finally.cs:205:17:205:47 | if (...) ... | Finally.cs:205:21:205:22 | access to parameter b2 | semmle.label | successor | -| Finally.cs:205:21:205:22 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:205:31:205:46 | [finally: exception(Exception)] object creation of type ExceptionB | semmle.label | true | -| Finally.cs:205:21:205:22 | [finally: exception(Exception)] access to parameter b2 | Finally.cs:208:13:210:13 | [finally: exception(Exception)] {...} | semmle.label | false | -| Finally.cs:205:21:205:22 | [finally: exception(ExceptionA)] access to parameter b2 | Finally.cs:205:31:205:46 | [finally: exception(ExceptionA)] object creation of type ExceptionB | semmle.label | true | -| 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(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(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(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(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(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(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(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(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(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(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(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(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(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 | -| Finally.cs:211:13:211:16 | [finally: exception(ExceptionA)] this access | Finally.cs:211:26:211:28 | [finally: exception(ExceptionA)] "0" | semmle.label | successor | -| Finally.cs:211:13:211:16 | this access | Finally.cs:211:26:211:28 | "0" | semmle.label | successor | -| Finally.cs:211:13:211:28 | ... = ... | Finally.cs:213:9:213:25 | ...; | semmle.label | successor | -| Finally.cs:211:13:211:28 | [finally: exception(Exception)] ... = ... | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(Exception) | -| Finally.cs:211:13:211:28 | [finally: exception(ExceptionA)] ... = ... | Finally.cs:195:10:195:12 | exit M10 (abnormal) | semmle.label | exception(ExceptionA) | -| Finally.cs:211:13:211:29 | ...; | Finally.cs:211:13:211:16 | this access | semmle.label | successor | -| Finally.cs:211:13:211:29 | [finally: exception(Exception)] ...; | Finally.cs:211:13:211:16 | [finally: exception(Exception)] this access | semmle.label | successor | -| Finally.cs:211:13:211:29 | [finally: exception(ExceptionA)] ...; | Finally.cs:211:13:211:16 | [finally: exception(ExceptionA)] this access | semmle.label | successor | -| Finally.cs:211:26:211:28 | "0" | Finally.cs:211:13:211:28 | ... = ... | semmle.label | successor | -| Finally.cs:211:26:211:28 | [finally: exception(Exception)] "0" | Finally.cs:211:13:211:28 | [finally: exception(Exception)] ... = ... | semmle.label | successor | -| Finally.cs:211:26:211:28 | [finally: exception(ExceptionA)] "0" | Finally.cs:211:13:211:28 | [finally: exception(ExceptionA)] ... = ... | semmle.label | successor | -| Finally.cs:213:9:213:12 | this access | Finally.cs:213:22:213:24 | "1" | semmle.label | successor | -| Finally.cs:213:9:213:24 | ... = ... | Finally.cs:195:10:195:12 | exit M10 (normal) | semmle.label | successor | -| Finally.cs:213:9:213:25 | ...; | Finally.cs:213:9:213:12 | this access | semmle.label | successor | -| Finally.cs:213:22:213:24 | "1" | Finally.cs:213:9:213:24 | ... = ... | semmle.label | successor | -| Finally.cs:216:10:216:12 | enter M11 | Finally.cs:217:5:231:5 | {...} | semmle.label | successor | -| Finally.cs:216:10:216:12 | exit M11 (normal) | Finally.cs:216:10:216:12 | exit M11 | semmle.label | successor | -| Finally.cs:217:5:231:5 | {...} | Finally.cs:218:9:229:9 | try {...} ... | semmle.label | successor | -| Finally.cs:218:9:229:9 | try {...} ... | Finally.cs:219:9:221:9 | {...} | semmle.label | successor | -| Finally.cs:219:9:221:9 | {...} | Finally.cs:220:13:220:37 | ...; | semmle.label | successor | -| Finally.cs:220:13:220:36 | call to method WriteLine | Finally.cs:222:9:225:9 | catch {...} | semmle.label | exception(Exception) | -| 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: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 | -| Finally.cs:224:13:224:39 | ...; | Finally.cs:224:31:224:37 | "Catch" | semmle.label | successor | -| Finally.cs:224:31:224:37 | "Catch" | Finally.cs:224:13:224:38 | call to method WriteLine | semmle.label | successor | -| Finally.cs:227:9:229:9 | {...} | Finally.cs:228:13:228:41 | ...; | semmle.label | successor | -| Finally.cs:228:13:228:40 | call to method WriteLine | Finally.cs:230:9:230:34 | ...; | semmle.label | successor | -| Finally.cs:228:13:228:41 | ...; | Finally.cs:228:31:228:39 | "Finally" | semmle.label | successor | -| Finally.cs:228:31:228:39 | "Finally" | Finally.cs:228:13:228:40 | call to method WriteLine | semmle.label | successor | -| 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(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(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(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(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(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(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(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(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(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(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(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 | -| 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: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.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 | 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: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: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: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 | -| 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 | -| 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 | -| Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:6:10:6:11 | exit M1 (normal) | semmle.label | empty | -| Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | Foreach.cs:8:22:8:24 | String arg | semmle.label | non-empty | -| Foreach.cs:8:22:8:24 | String arg | Foreach.cs:9:13:9:13 | ; | semmle.label | successor | -| Foreach.cs:8:29:8:32 | access to parameter args | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:9:13:9:13 | ; | Foreach.cs:8:9:9:13 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:12:10:12:11 | enter M2 | Foreach.cs:13:5:16:5 | {...} | semmle.label | successor | -| Foreach.cs:12:10:12:11 | exit M2 (normal) | Foreach.cs:12:10:12:11 | exit M2 | semmle.label | successor | -| Foreach.cs:13:5:16:5 | {...} | Foreach.cs:14:27:14:30 | access to parameter args | semmle.label | successor | -| Foreach.cs:14:9:15:13 | foreach (... ... in ...) ... | Foreach.cs:12:10:12:11 | exit M2 (normal) | semmle.label | empty | -| Foreach.cs:14:9:15:13 | foreach (... ... in ...) ... | Foreach.cs:14:22:14:22 | String _ | semmle.label | non-empty | -| Foreach.cs:14:22:14:22 | String _ | Foreach.cs:15:13:15:13 | ; | semmle.label | successor | -| Foreach.cs:14:27:14:30 | access to parameter args | Foreach.cs:14:9:15:13 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:15:13:15:13 | ; | Foreach.cs:14:9:15:13 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:18:10:18:11 | enter M3 | Foreach.cs:19:5:22:5 | {...} | semmle.label | successor | -| Foreach.cs:18:10:18:11 | exit M3 (normal) | Foreach.cs:18:10:18:11 | exit M3 | semmle.label | successor | -| Foreach.cs:19:5:22:5 | {...} | Foreach.cs:20:27:20:27 | access to parameter e | semmle.label | successor | -| Foreach.cs:20:9:21:11 | foreach (... ... in ...) ... | Foreach.cs:18:10:18:11 | exit M3 (normal) | semmle.label | empty | -| Foreach.cs:20:9:21:11 | foreach (... ... in ...) ... | Foreach.cs:20:22:20:22 | String x | semmle.label | non-empty | -| Foreach.cs:20:22:20:22 | String x | Foreach.cs:21:11:21:11 | ; | semmle.label | successor | -| Foreach.cs:20:27:20:27 | access to parameter e | Foreach.cs:20:29:20:38 | call to method ToArray | semmle.label | non-null | -| Foreach.cs:20:27:20:27 | access to parameter e | Foreach.cs:20:43:20:68 | call to method Empty | semmle.label | null | -| Foreach.cs:20:27:20:68 | ... ?? ... | Foreach.cs:20:9:21:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:20:29:20:38 | call to method ToArray | Foreach.cs:20:27:20:68 | ... ?? ... | semmle.label | non-null | -| Foreach.cs:20:29:20:38 | call to method ToArray | Foreach.cs:20:43:20:68 | call to method Empty | semmle.label | null | -| Foreach.cs:20:43:20:68 | call to method Empty | Foreach.cs:20:27:20:68 | ... ?? ... | semmle.label | successor | -| Foreach.cs:21:11:21:11 | ; | Foreach.cs:20:9:21:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:24:10:24:11 | enter M4 | Foreach.cs:25:5:28:5 | {...} | semmle.label | successor | -| Foreach.cs:24:10:24:11 | exit M4 (normal) | Foreach.cs:24:10:24:11 | exit M4 | semmle.label | successor | -| Foreach.cs:25:5:28:5 | {...} | Foreach.cs:26:36:26:39 | access to parameter args | semmle.label | successor | -| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:24:10:24:11 | exit M4 (normal) | semmle.label | empty | -| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:23:26:23 | String x | semmle.label | non-empty | -| Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:27:11:27:11 | ; | semmle.label | successor | -| Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:30:26:30 | Int32 y | semmle.label | successor | -| Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:18:26:31 | (..., ...) | semmle.label | successor | -| Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:27:11:27:11 | ; | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:30:10:30:11 | enter M5 | Foreach.cs:31:5:34:5 | {...} | semmle.label | successor | -| Foreach.cs:30:10:30:11 | exit M5 (normal) | Foreach.cs:30:10:30:11 | exit M5 | semmle.label | successor | -| Foreach.cs:31:5:34:5 | {...} | Foreach.cs:32:32:32:35 | access to parameter args | semmle.label | successor | -| Foreach.cs:32:9:33:11 | foreach (... ... in ...) ... | Foreach.cs:30:10:30:11 | exit M5 (normal) | semmle.label | empty | -| Foreach.cs:32:9:33:11 | foreach (... ... in ...) ... | Foreach.cs:32:23:32:23 | String x | semmle.label | non-empty | -| Foreach.cs:32:18:32:27 | (..., ...) | Foreach.cs:33:11:33:11 | ; | semmle.label | successor | -| Foreach.cs:32:23:32:23 | String x | Foreach.cs:32:26:32:26 | Int32 y | semmle.label | successor | -| Foreach.cs:32:26:32:26 | Int32 y | Foreach.cs:32:18:32:27 | (..., ...) | semmle.label | successor | -| Foreach.cs:32:32:32:35 | access to parameter args | Foreach.cs:32:9:33:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:33:11:33:11 | ; | Foreach.cs:32:9:33:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:36:10:36:11 | enter M6 | Foreach.cs:37:5:40:5 | {...} | semmle.label | successor | -| Foreach.cs:36:10:36:11 | exit M6 (normal) | Foreach.cs:36:10:36:11 | exit M6 | semmle.label | successor | -| Foreach.cs:37:5:40:5 | {...} | Foreach.cs:38:39:38:42 | access to parameter args | semmle.label | successor | -| Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | Foreach.cs:36:10:36:11 | exit M6 (normal) | semmle.label | empty | -| Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | Foreach.cs:38:26:38:26 | String x | semmle.label | non-empty | -| Foreach.cs:38:18:38:34 | (..., ...) | Foreach.cs:39:11:39:11 | ; | semmle.label | successor | -| Foreach.cs:38:26:38:26 | String x | Foreach.cs:38:33:38:33 | Int32 y | semmle.label | successor | -| Foreach.cs:38:33:38:33 | Int32 y | Foreach.cs:38:18:38:34 | (..., ...) | semmle.label | successor | -| Foreach.cs:38:39:38:42 | access to parameter args | Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Foreach.cs:39:11:39:11 | ; | Foreach.cs:38:9:39:11 | foreach (... ... in ...) ... | semmle.label | successor | -| Initializers.cs:5:9:5:9 | this access | Initializers.cs:5:13:5:13 | access to field H | semmle.label | successor | -| Initializers.cs:5:9:5:9 | this access | Initializers.cs:5:13:5:13 | access to field H | semmle.label | successor | -| Initializers.cs:5:9:5:17 | ... = ... | Initializers.cs:6:9:6:9 | this access | semmle.label | successor | -| Initializers.cs:5:9:5:17 | ... = ... | Initializers.cs:6:9:6:9 | this access | semmle.label | successor | -| Initializers.cs:5:13:5:13 | access to field H | Initializers.cs:5:17:5:17 | 1 | semmle.label | successor | -| Initializers.cs:5:13:5:13 | access to field H | Initializers.cs:5:17:5:17 | 1 | semmle.label | successor | -| Initializers.cs:5:13:5:17 | ... + ... | Initializers.cs:5:9:5:17 | ... = ... | semmle.label | successor | -| Initializers.cs:5:13:5:17 | ... + ... | Initializers.cs:5:9:5:17 | ... = ... | semmle.label | successor | -| Initializers.cs:5:17:5:17 | 1 | Initializers.cs:5:13:5:17 | ... + ... | semmle.label | successor | -| Initializers.cs:5:17:5:17 | 1 | Initializers.cs:5:13:5:17 | ... + ... | semmle.label | successor | -| Initializers.cs:6:9:6:9 | access to property G | Initializers.cs:6:25:6:31 | ... = ... | semmle.label | successor | -| Initializers.cs:6:9:6:9 | access to property G | Initializers.cs:6:25:6:31 | ... = ... | semmle.label | successor | -| Initializers.cs:6:9:6:9 | this access | Initializers.cs:6:27:6:27 | access to field H | semmle.label | successor | -| Initializers.cs:6:9:6:9 | this access | Initializers.cs:6:27:6:27 | access to field H | semmle.label | successor | -| Initializers.cs:6:25:6:31 | ... = ... | Initializers.cs:8:20:8:22 | {...} | semmle.label | successor | -| Initializers.cs:6:25:6:31 | ... = ... | Initializers.cs:10:28:10:30 | {...} | semmle.label | successor | -| Initializers.cs:6:27:6:27 | access to field H | Initializers.cs:6:31:6:31 | 2 | semmle.label | successor | -| Initializers.cs:6:27:6:27 | access to field H | Initializers.cs:6:31:6:31 | 2 | semmle.label | successor | -| Initializers.cs:6:27:6:31 | ... + ... | Initializers.cs:6:9:6:9 | access to property G | semmle.label | successor | -| Initializers.cs:6:27:6:31 | ... + ... | Initializers.cs:6:9:6:9 | access to property G | semmle.label | successor | -| Initializers.cs:6:31:6:31 | 2 | Initializers.cs:6:27:6:31 | ... + ... | semmle.label | successor | -| Initializers.cs:6:31:6:31 | 2 | Initializers.cs:6:27:6:31 | ... + ... | semmle.label | successor | -| Initializers.cs:8:5:8:16 | call to constructor Object | Initializers.cs:5:9:5:9 | this access | semmle.label | successor | -| Initializers.cs:8:5:8:16 | enter Initializers | Initializers.cs:8:5:8:16 | call to constructor Object | semmle.label | successor | -| Initializers.cs:8:5:8:16 | exit Initializers (normal) | Initializers.cs:8:5:8:16 | exit Initializers | semmle.label | successor | -| Initializers.cs:8:20:8:22 | {...} | Initializers.cs:8:5:8:16 | exit Initializers (normal) | semmle.label | successor | -| Initializers.cs:10:5:10:16 | call to constructor Object | Initializers.cs:5:9:5:9 | this access | semmle.label | successor | -| Initializers.cs:10:5:10:16 | enter Initializers | Initializers.cs:10:5:10:16 | call to constructor Object | semmle.label | successor | -| Initializers.cs:10:5:10:16 | exit Initializers (normal) | Initializers.cs:10:5:10:16 | exit Initializers | semmle.label | successor | -| Initializers.cs:10:28:10:30 | {...} | Initializers.cs:10:5:10:16 | exit Initializers (normal) | semmle.label | successor | -| Initializers.cs:12:10:12:10 | enter M | Initializers.cs:13:5:16:5 | {...} | semmle.label | successor | -| Initializers.cs:12:10:12:10 | exit M (normal) | Initializers.cs:12:10:12:10 | exit M | semmle.label | successor | -| Initializers.cs:13:5:16:5 | {...} | Initializers.cs:14:9:14:54 | ... ...; | semmle.label | successor | -| Initializers.cs:14:9:14:54 | ... ...; | Initializers.cs:14:34:14:35 | "" | semmle.label | successor | -| Initializers.cs:14:13:14:53 | Initializers i = ... | Initializers.cs:15:9:15:64 | ... ...; | semmle.label | successor | -| Initializers.cs:14:17:14:53 | object creation of type Initializers | Initializers.cs:14:44:14:44 | 0 | semmle.label | successor | -| Initializers.cs:14:34:14:35 | "" | Initializers.cs:14:17:14:53 | object creation of type Initializers | semmle.label | successor | -| Initializers.cs:14:38:14:53 | { ..., ... } | Initializers.cs:14:13:14:53 | Initializers i = ... | semmle.label | successor | -| Initializers.cs:14:40:14:44 | ... = ... | Initializers.cs:14:51:14:51 | 1 | semmle.label | successor | -| Initializers.cs:14:44:14:44 | 0 | Initializers.cs:14:40:14:44 | ... = ... | semmle.label | successor | -| Initializers.cs:14:47:14:47 | access to property G | Initializers.cs:14:47:14:51 | ... = ... | semmle.label | successor | -| Initializers.cs:14:47:14:51 | ... = ... | Initializers.cs:14:38:14:53 | { ..., ... } | semmle.label | successor | -| Initializers.cs:14:51:14:51 | 1 | Initializers.cs:14:47:14:47 | access to property G | semmle.label | successor | -| Initializers.cs:15:9:15:64 | ... ...; | Initializers.cs:15:18:15:63 | 2 | semmle.label | successor | -| Initializers.cs:15:13:15:63 | Initializers[] iz = ... | Initializers.cs:12:10:12:10 | exit M (normal) | semmle.label | successor | -| Initializers.cs:15:18:15:63 | 2 | Initializers.cs:15:18:15:63 | array creation of type Initializers[] | semmle.label | successor | -| Initializers.cs:15:18:15:63 | array creation of type Initializers[] | Initializers.cs:15:39:15:39 | access to local variable i | semmle.label | successor | -| Initializers.cs:15:37:15:63 | { ..., ... } | Initializers.cs:15:13:15:63 | Initializers[] iz = ... | semmle.label | successor | -| Initializers.cs:15:39:15:39 | access to local variable i | Initializers.cs:15:59:15:60 | "" | semmle.label | successor | -| Initializers.cs:15:42:15:61 | object creation of type Initializers | Initializers.cs:15:37:15:63 | { ..., ... } | semmle.label | successor | -| Initializers.cs:15:59:15:60 | "" | Initializers.cs:15:42:15:61 | object creation of type Initializers | semmle.label | successor | -| Initializers.cs:18:16:18:16 | enter H | Initializers.cs:18:20:18:20 | 1 | semmle.label | successor | -| Initializers.cs:18:20:18:20 | 1 | Initializers.cs:18:16:18:20 | ... = ... | semmle.label | successor | -| Initializers.cs:20:11:20:23 | enter NoConstructor | Initializers.cs:22:23:22:23 | this access | semmle.label | successor | -| Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | Initializers.cs:20:11:20:23 | exit NoConstructor | semmle.label | successor | -| Initializers.cs:22:23:22:23 | this access | Initializers.cs:22:27:22:27 | 0 | semmle.label | successor | -| Initializers.cs:22:23:22:27 | ... = ... | Initializers.cs:23:23:23:23 | this access | semmle.label | successor | -| Initializers.cs:22:27:22:27 | 0 | Initializers.cs:22:23:22:27 | ... = ... | semmle.label | successor | -| Initializers.cs:23:23:23:23 | this access | Initializers.cs:23:27:23:27 | 1 | semmle.label | successor | -| Initializers.cs:23:23:23:27 | ... = ... | Initializers.cs:20:11:20:23 | exit NoConstructor (normal) | semmle.label | successor | -| Initializers.cs:23:27:23:27 | 1 | Initializers.cs:23:23:23:27 | ... = ... | semmle.label | successor | -| Initializers.cs:28:13:28:13 | this access | Initializers.cs:28:17:28:17 | 2 | semmle.label | successor | -| Initializers.cs:28:13:28:13 | this access | Initializers.cs:28:17:28:17 | 2 | semmle.label | successor | -| Initializers.cs:28:13:28:17 | ... = ... | Initializers.cs:31:24:31:33 | {...} | semmle.label | successor | -| Initializers.cs:28:13:28:17 | ... = ... | Initializers.cs:35:27:35:40 | {...} | semmle.label | successor | -| Initializers.cs:28:17:28:17 | 2 | Initializers.cs:28:13:28:17 | ... = ... | semmle.label | successor | -| Initializers.cs:28:17:28:17 | 2 | Initializers.cs:28:13:28:17 | ... = ... | semmle.label | successor | -| Initializers.cs:31:9:31:11 | enter Sub | Initializers.cs:31:17:31:20 | call to constructor NoConstructor | semmle.label | successor | -| Initializers.cs:31:9:31:11 | exit Sub (normal) | Initializers.cs:31:9:31:11 | exit Sub | semmle.label | successor | -| Initializers.cs:31:17:31:20 | call to constructor NoConstructor | Initializers.cs:28:13:28:13 | this access | semmle.label | successor | -| Initializers.cs:31:24:31:33 | {...} | Initializers.cs:31:26:31:31 | ...; | semmle.label | successor | -| Initializers.cs:31:26:31:26 | this access | Initializers.cs:31:30:31:30 | 3 | semmle.label | successor | -| Initializers.cs:31:26:31:30 | ... = ... | Initializers.cs:31:9:31:11 | exit Sub (normal) | semmle.label | successor | -| Initializers.cs:31:26:31:31 | ...; | Initializers.cs:31:26:31:26 | this access | semmle.label | successor | -| Initializers.cs:31:30:31:30 | 3 | Initializers.cs:31:26:31:30 | ... = ... | semmle.label | successor | -| Initializers.cs:33:9:33:11 | enter Sub | Initializers.cs:33:22:33:25 | call to constructor Sub | semmle.label | successor | -| Initializers.cs:33:9:33:11 | exit Sub (normal) | Initializers.cs:33:9:33:11 | exit Sub | semmle.label | successor | -| Initializers.cs:33:22:33:25 | call to constructor Sub | Initializers.cs:33:29:33:38 | {...} | semmle.label | successor | -| Initializers.cs:33:29:33:38 | {...} | Initializers.cs:33:31:33:36 | ...; | semmle.label | successor | -| Initializers.cs:33:31:33:31 | this access | Initializers.cs:33:35:33:35 | access to parameter i | semmle.label | successor | -| Initializers.cs:33:31:33:35 | ... = ... | Initializers.cs:33:9:33:11 | exit Sub (normal) | semmle.label | successor | -| Initializers.cs:33:31:33:36 | ...; | Initializers.cs:33:31:33:31 | this access | semmle.label | successor | -| Initializers.cs:33:35:33:35 | access to parameter i | Initializers.cs:33:31:33:35 | ... = ... | semmle.label | successor | -| Initializers.cs:35:9:35:11 | call to constructor NoConstructor | Initializers.cs:28:13:28:13 | this access | semmle.label | successor | -| Initializers.cs:35:9:35:11 | enter Sub | Initializers.cs:35:9:35:11 | call to constructor NoConstructor | semmle.label | successor | -| Initializers.cs:35:9:35:11 | exit Sub (normal) | Initializers.cs:35:9:35:11 | exit Sub | semmle.label | successor | -| Initializers.cs:35:27:35:40 | {...} | Initializers.cs:35:29:35:38 | ...; | semmle.label | successor | -| Initializers.cs:35:29:35:29 | this access | Initializers.cs:35:33:35:33 | access to parameter i | semmle.label | successor | -| Initializers.cs:35:29:35:37 | ... = ... | Initializers.cs:35:9:35:11 | exit Sub (normal) | semmle.label | successor | -| Initializers.cs:35:29:35:38 | ...; | Initializers.cs:35:29:35:29 | this access | semmle.label | successor | -| Initializers.cs:35:33:35:33 | access to parameter i | Initializers.cs:35:37:35:37 | access to parameter j | semmle.label | successor | -| Initializers.cs:35:33:35:37 | ... + ... | Initializers.cs:35:29:35:37 | ... = ... | semmle.label | successor | -| Initializers.cs:35:37:35:37 | access to parameter j | Initializers.cs:35:33:35:37 | ... + ... | semmle.label | successor | -| Initializers.cs:51:10:51:13 | enter Test | Initializers.cs:52:5:66:5 | {...} | semmle.label | successor | -| Initializers.cs:51:10:51:13 | exit Test (normal) | Initializers.cs:51:10:51:13 | exit Test | semmle.label | successor | -| Initializers.cs:52:5:66:5 | {...} | Initializers.cs:54:9:54:96 | ... ...; | semmle.label | successor | -| Initializers.cs:54:9:54:96 | ... ...; | Initializers.cs:54:20:54:95 | object creation of type Dictionary | semmle.label | successor | -| Initializers.cs:54:13:54:95 | Dictionary dict = ... | Initializers.cs:57:9:65:10 | ... ...; | semmle.label | successor | -| Initializers.cs:54:20:54:95 | object creation of type Dictionary | Initializers.cs:54:53:54:53 | 0 | semmle.label | successor | -| Initializers.cs:54:50:54:95 | { ..., ... } | Initializers.cs:54:13:54:95 | Dictionary dict = ... | semmle.label | successor | -| Initializers.cs:54:52:54:54 | access to indexer | Initializers.cs:54:52:54:63 | ... = ... | semmle.label | successor | -| Initializers.cs:54:52:54:63 | ... = ... | Initializers.cs:54:67:54:67 | 1 | semmle.label | successor | -| Initializers.cs:54:53:54:53 | 0 | Initializers.cs:54:58:54:63 | "Zero" | semmle.label | successor | -| Initializers.cs:54:58:54:63 | "Zero" | Initializers.cs:54:52:54:54 | access to indexer | semmle.label | successor | -| Initializers.cs:54:66:54:68 | access to indexer | Initializers.cs:54:66:54:76 | ... = ... | semmle.label | successor | -| Initializers.cs:54:66:54:76 | ... = ... | Initializers.cs:54:80:54:80 | access to parameter i | semmle.label | successor | -| Initializers.cs:54:67:54:67 | 1 | Initializers.cs:54:72:54:76 | "One" | semmle.label | successor | -| Initializers.cs:54:72:54:76 | "One" | Initializers.cs:54:66:54:68 | access to indexer | semmle.label | successor | -| Initializers.cs:54:79:54:85 | access to indexer | Initializers.cs:54:79:54:93 | ... = ... | semmle.label | successor | -| Initializers.cs:54:79:54:93 | ... = ... | Initializers.cs:54:50:54:95 | { ..., ... } | semmle.label | successor | -| Initializers.cs:54:80:54:80 | access to parameter i | Initializers.cs:54:84:54:84 | 2 | semmle.label | successor | -| Initializers.cs:54:80:54:84 | ... + ... | Initializers.cs:54:89:54:93 | "Two" | semmle.label | successor | -| Initializers.cs:54:84:54:84 | 2 | Initializers.cs:54:80:54:84 | ... + ... | semmle.label | successor | -| Initializers.cs:54:89:54:93 | "Two" | Initializers.cs:54:79:54:85 | access to indexer | semmle.label | successor | -| Initializers.cs:57:9:65:10 | ... ...; | Initializers.cs:57:24:65:9 | object creation of type Compound | semmle.label | successor | -| Initializers.cs:57:13:65:9 | Compound compound = ... | Initializers.cs:51:10:51:13 | exit Test (normal) | semmle.label | successor | -| Initializers.cs:57:24:65:9 | object creation of type Compound | Initializers.cs:59:34:59:34 | 0 | semmle.label | successor | -| Initializers.cs:58:9:65:9 | { ..., ... } | Initializers.cs:57:13:65:9 | Compound compound = ... | semmle.label | successor | -| Initializers.cs:59:13:59:76 | ... = ... | Initializers.cs:60:37:60:37 | 3 | semmle.label | successor | -| Initializers.cs:59:31:59:76 | { ..., ... } | Initializers.cs:59:13:59:76 | ... = ... | semmle.label | successor | -| Initializers.cs:59:33:59:35 | access to indexer | Initializers.cs:59:33:59:44 | ... = ... | semmle.label | successor | -| Initializers.cs:59:33:59:44 | ... = ... | Initializers.cs:59:48:59:48 | 1 | semmle.label | successor | -| Initializers.cs:59:34:59:34 | 0 | Initializers.cs:59:39:59:44 | "Zero" | semmle.label | successor | -| Initializers.cs:59:39:59:44 | "Zero" | Initializers.cs:59:33:59:35 | access to indexer | semmle.label | successor | -| Initializers.cs:59:47:59:49 | access to indexer | Initializers.cs:59:47:59:57 | ... = ... | semmle.label | successor | -| Initializers.cs:59:47:59:57 | ... = ... | Initializers.cs:59:61:59:61 | access to parameter i | semmle.label | successor | -| Initializers.cs:59:48:59:48 | 1 | Initializers.cs:59:53:59:57 | "One" | semmle.label | successor | -| Initializers.cs:59:53:59:57 | "One" | Initializers.cs:59:47:59:49 | access to indexer | semmle.label | successor | -| Initializers.cs:59:60:59:66 | access to indexer | Initializers.cs:59:60:59:74 | ... = ... | semmle.label | successor | -| Initializers.cs:59:60:59:74 | ... = ... | Initializers.cs:59:31:59:76 | { ..., ... } | semmle.label | successor | -| Initializers.cs:59:61:59:61 | access to parameter i | Initializers.cs:59:65:59:65 | 2 | semmle.label | successor | -| Initializers.cs:59:61:59:65 | ... + ... | Initializers.cs:59:70:59:74 | "Two" | semmle.label | successor | -| Initializers.cs:59:65:59:65 | 2 | Initializers.cs:59:61:59:65 | ... + ... | semmle.label | successor | -| Initializers.cs:59:70:59:74 | "Two" | Initializers.cs:59:60:59:66 | access to indexer | semmle.label | successor | -| Initializers.cs:60:13:60:30 | access to property DictionaryProperty | Initializers.cs:60:13:60:80 | ... = ... | semmle.label | successor | -| Initializers.cs:60:13:60:80 | ... = ... | Initializers.cs:61:29:61:29 | 0 | semmle.label | successor | -| Initializers.cs:60:34:60:80 | { ..., ... } | Initializers.cs:60:13:60:30 | access to property DictionaryProperty | semmle.label | successor | -| Initializers.cs:60:36:60:38 | access to indexer | Initializers.cs:60:36:60:48 | ... = ... | semmle.label | successor | -| Initializers.cs:60:36:60:48 | ... = ... | Initializers.cs:60:52:60:52 | 2 | semmle.label | successor | -| Initializers.cs:60:37:60:37 | 3 | Initializers.cs:60:42:60:48 | "Three" | semmle.label | successor | -| Initializers.cs:60:42:60:48 | "Three" | Initializers.cs:60:36:60:38 | access to indexer | semmle.label | successor | -| Initializers.cs:60:51:60:53 | access to indexer | Initializers.cs:60:51:60:61 | ... = ... | semmle.label | successor | -| Initializers.cs:60:51:60:61 | ... = ... | Initializers.cs:60:65:60:65 | access to parameter i | semmle.label | successor | -| Initializers.cs:60:52:60:52 | 2 | Initializers.cs:60:57:60:61 | "Two" | semmle.label | successor | -| Initializers.cs:60:57:60:61 | "Two" | Initializers.cs:60:51:60:53 | access to indexer | semmle.label | successor | -| Initializers.cs:60:64:60:70 | access to indexer | Initializers.cs:60:64:60:78 | ... = ... | semmle.label | successor | -| Initializers.cs:60:64:60:78 | ... = ... | Initializers.cs:60:34:60:80 | { ..., ... } | semmle.label | successor | -| Initializers.cs:60:65:60:65 | access to parameter i | Initializers.cs:60:69:60:69 | 1 | semmle.label | successor | -| Initializers.cs:60:65:60:69 | ... + ... | Initializers.cs:60:74:60:78 | "One" | semmle.label | successor | -| Initializers.cs:60:69:60:69 | 1 | Initializers.cs:60:65:60:69 | ... + ... | semmle.label | successor | -| Initializers.cs:60:74:60:78 | "One" | Initializers.cs:60:64:60:70 | access to indexer | semmle.label | successor | -| Initializers.cs:61:13:61:58 | ... = ... | Initializers.cs:62:30:62:30 | 0 | semmle.label | successor | -| Initializers.cs:61:26:61:58 | { ..., ... } | Initializers.cs:61:13:61:58 | ... = ... | semmle.label | successor | -| Initializers.cs:61:28:61:39 | ... = ... | Initializers.cs:61:43:61:43 | access to parameter i | semmle.label | successor | -| Initializers.cs:61:29:61:29 | 0 | Initializers.cs:61:34:61:39 | "Zero" | semmle.label | successor | -| Initializers.cs:61:34:61:39 | "Zero" | Initializers.cs:61:28:61:39 | ... = ... | semmle.label | successor | -| Initializers.cs:61:42:61:56 | ... = ... | Initializers.cs:61:26:61:58 | { ..., ... } | semmle.label | successor | -| Initializers.cs:61:43:61:43 | access to parameter i | Initializers.cs:61:47:61:47 | 1 | semmle.label | successor | -| Initializers.cs:61:43:61:47 | ... + ... | Initializers.cs:61:52:61:56 | "One" | semmle.label | successor | -| Initializers.cs:61:47:61:47 | 1 | Initializers.cs:61:43:61:47 | ... + ... | semmle.label | successor | -| Initializers.cs:61:52:61:56 | "One" | Initializers.cs:61:42:61:56 | ... = ... | semmle.label | successor | -| Initializers.cs:62:13:62:60 | ... = ... | Initializers.cs:63:32:63:32 | 1 | semmle.label | successor | -| Initializers.cs:62:27:62:60 | { ..., ... } | Initializers.cs:62:13:62:60 | ... = ... | semmle.label | successor | -| Initializers.cs:62:29:62:40 | ... = ... | Initializers.cs:62:44:62:44 | 1 | semmle.label | successor | -| Initializers.cs:62:30:62:30 | 0 | Initializers.cs:62:33:62:33 | 1 | semmle.label | successor | -| Initializers.cs:62:33:62:33 | 1 | Initializers.cs:62:38:62:40 | "i" | semmle.label | successor | -| Initializers.cs:62:38:62:40 | "i" | Initializers.cs:62:29:62:40 | ... = ... | semmle.label | successor | -| Initializers.cs:62:43:62:58 | ... = ... | Initializers.cs:62:27:62:60 | { ..., ... } | semmle.label | successor | -| Initializers.cs:62:44:62:44 | 1 | Initializers.cs:62:47:62:47 | access to parameter i | semmle.label | successor | -| Initializers.cs:62:47:62:47 | access to parameter i | Initializers.cs:62:51:62:51 | 0 | semmle.label | successor | -| Initializers.cs:62:47:62:51 | ... + ... | Initializers.cs:62:56:62:58 | "1" | semmle.label | successor | -| Initializers.cs:62:51:62:51 | 0 | Initializers.cs:62:47:62:51 | ... + ... | semmle.label | successor | -| Initializers.cs:62:56:62:58 | "1" | Initializers.cs:62:43:62:58 | ... = ... | semmle.label | successor | -| Initializers.cs:63:13:63:25 | access to property ArrayProperty | Initializers.cs:63:13:63:60 | ... = ... | semmle.label | successor | -| Initializers.cs:63:13:63:60 | ... = ... | Initializers.cs:64:33:64:33 | 0 | semmle.label | successor | -| Initializers.cs:63:29:63:60 | { ..., ... } | Initializers.cs:63:13:63:25 | access to property ArrayProperty | semmle.label | successor | -| Initializers.cs:63:31:63:41 | ... = ... | Initializers.cs:63:45:63:45 | access to parameter i | semmle.label | successor | -| Initializers.cs:63:32:63:32 | 1 | Initializers.cs:63:37:63:41 | "One" | semmle.label | successor | -| Initializers.cs:63:37:63:41 | "One" | Initializers.cs:63:31:63:41 | ... = ... | semmle.label | successor | -| Initializers.cs:63:44:63:58 | ... = ... | Initializers.cs:63:29:63:60 | { ..., ... } | semmle.label | successor | -| Initializers.cs:63:45:63:45 | access to parameter i | Initializers.cs:63:49:63:49 | 2 | semmle.label | successor | -| Initializers.cs:63:45:63:49 | ... + ... | Initializers.cs:63:54:63:58 | "Two" | semmle.label | successor | -| Initializers.cs:63:49:63:49 | 2 | Initializers.cs:63:45:63:49 | ... + ... | semmle.label | successor | -| Initializers.cs:63:54:63:58 | "Two" | Initializers.cs:63:44:63:58 | ... = ... | semmle.label | successor | -| Initializers.cs:64:13:64:26 | access to property ArrayProperty2 | Initializers.cs:64:13:64:63 | ... = ... | semmle.label | successor | -| Initializers.cs:64:13:64:63 | ... = ... | Initializers.cs:58:9:65:9 | { ..., ... } | semmle.label | successor | -| Initializers.cs:64:30:64:63 | { ..., ... } | Initializers.cs:64:13:64:26 | access to property ArrayProperty2 | semmle.label | successor | -| Initializers.cs:64:32:64:43 | ... = ... | Initializers.cs:64:47:64:47 | 1 | semmle.label | successor | -| Initializers.cs:64:33:64:33 | 0 | Initializers.cs:64:36:64:36 | 1 | semmle.label | successor | -| Initializers.cs:64:36:64:36 | 1 | Initializers.cs:64:41:64:43 | "i" | semmle.label | successor | -| Initializers.cs:64:41:64:43 | "i" | Initializers.cs:64:32:64:43 | ... = ... | semmle.label | successor | -| Initializers.cs:64:46:64:61 | ... = ... | Initializers.cs:64:30:64:63 | { ..., ... } | semmle.label | successor | -| Initializers.cs:64:47:64:47 | 1 | Initializers.cs:64:50:64:50 | access to parameter i | semmle.label | successor | -| Initializers.cs:64:50:64:50 | access to parameter i | Initializers.cs:64:54:64:54 | 0 | semmle.label | successor | -| Initializers.cs:64:50:64:54 | ... + ... | Initializers.cs:64:59:64:61 | "1" | semmle.label | successor | -| Initializers.cs:64:54:64:54 | 0 | Initializers.cs:64:50:64:54 | ... + ... | semmle.label | successor | -| Initializers.cs:64:59:64:61 | "1" | Initializers.cs:64:46:64:61 | ... = ... | semmle.label | successor | -| LoopUnrolling.cs:7:10:7:11 | enter M1 | LoopUnrolling.cs:8:5:13:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:7:10:7:11 | exit M1 (normal) | LoopUnrolling.cs:7:10:7:11 | exit M1 | semmle.label | successor | -| LoopUnrolling.cs:8:5:13:5 | {...} | LoopUnrolling.cs:9:9:10:19 | if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:9:9:10:19 | if (...) ... | LoopUnrolling.cs:9:13:9:16 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:9:13:9:16 | access to parameter args | LoopUnrolling.cs:9:13:9:23 | access to property Length | semmle.label | successor | -| LoopUnrolling.cs:9:13:9:23 | access to property Length | LoopUnrolling.cs:9:28:9:28 | 0 | semmle.label | successor | -| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:10:13:10:19 | return ...; | semmle.label | true | -| LoopUnrolling.cs:9:13:9:28 | ... == ... | LoopUnrolling.cs:11:29:11:32 | access to parameter args | semmle.label | false | -| LoopUnrolling.cs:9:28:9:28 | 0 | LoopUnrolling.cs:9:13:9:28 | ... == ... | semmle.label | successor | -| LoopUnrolling.cs:10:13:10:19 | return ...; | LoopUnrolling.cs:7:10:7:11 | exit M1 (normal) | semmle.label | return | -| LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | LoopUnrolling.cs:11:22:11:24 | String arg | semmle.label | non-empty | -| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:7:10:7:11 | exit M1 (normal) | semmle.label | empty | -| LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | LoopUnrolling.cs:11:22:11:24 | String arg | semmle.label | non-empty | -| LoopUnrolling.cs:11:22:11:24 | String arg | LoopUnrolling.cs:12:13:12:35 | ...; | semmle.label | successor | -| LoopUnrolling.cs:11:29:11:32 | access to parameter args | LoopUnrolling.cs:11:9:12:35 | [unroll (line 11)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | LoopUnrolling.cs:11:9:12:35 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:12:13:12:35 | ...; | LoopUnrolling.cs:12:31:12:33 | access to local variable arg | semmle.label | successor | -| LoopUnrolling.cs:12:31:12:33 | access to local variable arg | LoopUnrolling.cs:12:13:12:34 | call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:15:10:15:11 | enter M2 | LoopUnrolling.cs:16:5:20:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:15:10:15:11 | exit M2 (normal) | LoopUnrolling.cs:15:10:15:11 | exit M2 | semmle.label | successor | -| LoopUnrolling.cs:16:5:20:5 | {...} | LoopUnrolling.cs:17:9:17:48 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:17:9:17:48 | ... ...; | LoopUnrolling.cs:17:18:17:47 | 3 | semmle.label | successor | -| LoopUnrolling.cs:17:13:17:47 | String[] xs = ... | LoopUnrolling.cs:18:27:18:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:17:18:17:47 | 3 | LoopUnrolling.cs:17:18:17:47 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:17:18:17:47 | array creation of type String[] | LoopUnrolling.cs:17:33:17:35 | "a" | semmle.label | successor | -| LoopUnrolling.cs:17:31:17:47 | { ..., ... } | LoopUnrolling.cs:17:13:17:47 | String[] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:17:33:17:35 | "a" | LoopUnrolling.cs:17:38:17:40 | "b" | semmle.label | successor | -| LoopUnrolling.cs:17:38:17:40 | "b" | LoopUnrolling.cs:17:43:17:45 | "c" | semmle.label | successor | -| LoopUnrolling.cs:17:43:17:45 | "c" | LoopUnrolling.cs:17:31:17:47 | { ..., ... } | semmle.label | successor | -| LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | LoopUnrolling.cs:18:22:18:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:15:10:15:11 | exit M2 (normal) | semmle.label | empty | -| LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | LoopUnrolling.cs:18:22:18:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:18:22:18:22 | String x | LoopUnrolling.cs:19:13:19:33 | ...; | semmle.label | successor | -| LoopUnrolling.cs:18:27:18:28 | access to local variable xs | LoopUnrolling.cs:18:9:19:33 | [unroll (line 18)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | LoopUnrolling.cs:18:9:19:33 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:19:13:19:33 | ...; | LoopUnrolling.cs:19:31:19:31 | access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:19:31:19:31 | access to local variable x | LoopUnrolling.cs:19:13:19:32 | call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:22:10:22:11 | enter M3 | LoopUnrolling.cs:23:5:27:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:22:10:22:11 | exit M3 (normal) | LoopUnrolling.cs:22:10:22:11 | exit M3 | semmle.label | successor | -| LoopUnrolling.cs:23:5:27:5 | {...} | LoopUnrolling.cs:24:29:24:32 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:22:10:22:11 | exit M3 (normal) | semmle.label | empty | -| LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:22:24:24 | Char arg | semmle.label | non-empty | -| LoopUnrolling.cs:24:22:24:24 | Char arg | LoopUnrolling.cs:25:34:25:37 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:24:29:24:32 | access to parameter args | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 | semmle.label | non-empty | -| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:24:9:26:40 | foreach (... ... in ...) ... | semmle.label | empty | -| LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | LoopUnrolling.cs:25:26:25:29 | Char arg0 | semmle.label | non-empty | -| LoopUnrolling.cs:25:26:25:29 | Char arg0 | LoopUnrolling.cs:26:17:26:40 | ...; | semmle.label | successor | -| LoopUnrolling.cs:25:34:25:37 | access to parameter args | LoopUnrolling.cs:25:13:26:40 | [unroll (line 25)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | LoopUnrolling.cs:25:13:26:40 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:26:17:26:40 | ...; | LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | semmle.label | successor | -| LoopUnrolling.cs:26:35:26:38 | access to local variable arg0 | LoopUnrolling.cs:26:17:26:39 | call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:29:10:29:11 | enter M4 | LoopUnrolling.cs:30:5:34:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:29:10:29:11 | exit M4 (normal) | LoopUnrolling.cs:29:10:29:11 | exit M4 | semmle.label | successor | -| LoopUnrolling.cs:30:5:34:5 | {...} | LoopUnrolling.cs:31:9:31:31 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:31:9:31:31 | ... ...; | LoopUnrolling.cs:31:29:31:29 | 0 | semmle.label | successor | -| LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | LoopUnrolling.cs:32:27:32:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | LoopUnrolling.cs:31:13:31:30 | String[] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:31:29:31:29 | 0 | LoopUnrolling.cs:31:18:31:30 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:32:9:33:33 | [skip (line 32)] foreach (... ... in ...) ... | LoopUnrolling.cs:29:10:29:11 | exit M4 (normal) | semmle.label | empty | -| LoopUnrolling.cs:32:27:32:28 | access to local variable xs | LoopUnrolling.cs:32:9:33:33 | [skip (line 32)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:36:10:36:11 | enter M5 | LoopUnrolling.cs:37:5:43:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:36:10:36:11 | exit M5 (normal) | LoopUnrolling.cs:36:10:36:11 | exit M5 | semmle.label | successor | -| LoopUnrolling.cs:37:5:43:5 | {...} | LoopUnrolling.cs:38:9:38:48 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:38:9:38:48 | ... ...; | LoopUnrolling.cs:38:18:38:47 | 3 | semmle.label | successor | -| LoopUnrolling.cs:38:13:38:47 | String[] xs = ... | LoopUnrolling.cs:39:9:39:48 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:38:18:38:47 | 3 | LoopUnrolling.cs:38:18:38:47 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:38:18:38:47 | array creation of type String[] | LoopUnrolling.cs:38:33:38:35 | "a" | semmle.label | successor | -| LoopUnrolling.cs:38:31:38:47 | { ..., ... } | LoopUnrolling.cs:38:13:38:47 | String[] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:38:33:38:35 | "a" | LoopUnrolling.cs:38:38:38:40 | "b" | semmle.label | successor | -| LoopUnrolling.cs:38:38:38:40 | "b" | LoopUnrolling.cs:38:43:38:45 | "c" | semmle.label | successor | -| LoopUnrolling.cs:38:43:38:45 | "c" | LoopUnrolling.cs:38:31:38:47 | { ..., ... } | semmle.label | successor | -| LoopUnrolling.cs:39:9:39:48 | ... ...; | LoopUnrolling.cs:39:18:39:47 | 3 | semmle.label | successor | -| LoopUnrolling.cs:39:13:39:47 | String[] ys = ... | LoopUnrolling.cs:40:27:40:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:39:18:39:47 | 3 | LoopUnrolling.cs:39:18:39:47 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:39:18:39:47 | array creation of type String[] | LoopUnrolling.cs:39:33:39:35 | "0" | semmle.label | successor | -| LoopUnrolling.cs:39:31:39:47 | { ..., ... } | LoopUnrolling.cs:39:13:39:47 | String[] ys = ... | semmle.label | successor | -| LoopUnrolling.cs:39:33:39:35 | "0" | LoopUnrolling.cs:39:38:39:40 | "1" | semmle.label | successor | -| LoopUnrolling.cs:39:38:39:40 | "1" | LoopUnrolling.cs:39:43:39:45 | "2" | semmle.label | successor | -| LoopUnrolling.cs:39:43:39:45 | "2" | LoopUnrolling.cs:39:31:39:47 | { ..., ... } | semmle.label | successor | -| LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | LoopUnrolling.cs:40:22:40:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:36:10:36:11 | exit M5 (normal) | semmle.label | empty | -| LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:22:40:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:40:22:40:22 | String x | LoopUnrolling.cs:41:31:41:32 | access to local variable ys | semmle.label | successor | -| LoopUnrolling.cs:40:27:40:28 | access to local variable xs | LoopUnrolling.cs:40:9:42:41 | [unroll (line 40)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | LoopUnrolling.cs:41:26:41:26 | String y | semmle.label | non-empty | -| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:40:9:42:41 | foreach (... ... in ...) ... | semmle.label | empty | -| LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | LoopUnrolling.cs:41:26:41:26 | String y | semmle.label | non-empty | -| LoopUnrolling.cs:41:26:41:26 | String y | LoopUnrolling.cs:42:17:42:41 | ...; | semmle.label | successor | -| LoopUnrolling.cs:41:31:41:32 | access to local variable ys | LoopUnrolling.cs:41:13:42:41 | [unroll (line 41)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | LoopUnrolling.cs:41:13:42:41 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:42:17:42:41 | ...; | LoopUnrolling.cs:42:35:42:35 | access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:42:35:42:35 | access to local variable x | LoopUnrolling.cs:42:39:42:39 | access to local variable y | semmle.label | successor | -| LoopUnrolling.cs:42:35:42:39 | ... + ... | LoopUnrolling.cs:42:17:42:40 | call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:42:39:42:39 | access to local variable y | LoopUnrolling.cs:42:35:42:39 | ... + ... | semmle.label | successor | -| LoopUnrolling.cs:45:10:45:11 | enter M6 | LoopUnrolling.cs:46:5:53:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:46:5:53:5 | {...} | LoopUnrolling.cs:47:9:47:48 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:47:9:47:48 | ... ...; | LoopUnrolling.cs:47:18:47:47 | 3 | semmle.label | successor | -| LoopUnrolling.cs:47:13:47:47 | String[] xs = ... | LoopUnrolling.cs:48:27:48:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:47:18:47:47 | 3 | LoopUnrolling.cs:47:18:47:47 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:47:18:47:47 | array creation of type String[] | LoopUnrolling.cs:47:33:47:35 | "a" | semmle.label | successor | -| LoopUnrolling.cs:47:31:47:47 | { ..., ... } | LoopUnrolling.cs:47:13:47:47 | String[] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:47:33:47:35 | "a" | LoopUnrolling.cs:47:38:47:40 | "b" | semmle.label | successor | -| LoopUnrolling.cs:47:38:47:40 | "b" | LoopUnrolling.cs:47:43:47:45 | "c" | semmle.label | successor | -| LoopUnrolling.cs:47:43:47:45 | "c" | LoopUnrolling.cs:47:31:47:47 | { ..., ... } | semmle.label | successor | -| LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | LoopUnrolling.cs:48:22:48:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:48:22:48:22 | String x | LoopUnrolling.cs:49:9:52:9 | {...} | semmle.label | successor | -| LoopUnrolling.cs:48:27:48:28 | access to local variable xs | LoopUnrolling.cs:48:9:52:9 | [unroll (line 48)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:49:9:52:9 | {...} | LoopUnrolling.cs:50:9:50:13 | Label: | semmle.label | successor | -| LoopUnrolling.cs:50:9:50:13 | Label: | LoopUnrolling.cs:50:16:50:36 | ...; | semmle.label | successor | -| LoopUnrolling.cs:50:16:50:35 | call to method WriteLine | LoopUnrolling.cs:51:13:51:23 | goto ...; | semmle.label | successor | -| LoopUnrolling.cs:50:16:50:36 | ...; | LoopUnrolling.cs:50:34:50:34 | access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:50:34:50:34 | access to local variable x | LoopUnrolling.cs:50:16:50:35 | call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:51:13:51:23 | goto ...; | LoopUnrolling.cs:50:9:50:13 | Label: | semmle.label | goto(Label) | -| LoopUnrolling.cs:55:10:55:11 | enter M7 | LoopUnrolling.cs:56:5:65:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:55:10:55:11 | exit M7 (normal) | LoopUnrolling.cs:55:10:55:11 | exit M7 | semmle.label | successor | -| LoopUnrolling.cs:56:5:65:5 | {...} | LoopUnrolling.cs:57:9:57:48 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:57:9:57:48 | ... ...; | LoopUnrolling.cs:57:18:57:47 | 3 | semmle.label | successor | -| LoopUnrolling.cs:57:13:57:47 | String[] xs = ... | LoopUnrolling.cs:58:27:58:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:57:18:57:47 | 3 | LoopUnrolling.cs:57:18:57:47 | array creation of type String[] | semmle.label | successor | -| LoopUnrolling.cs:57:18:57:47 | array creation of type String[] | LoopUnrolling.cs:57:33:57:35 | "a" | semmle.label | successor | -| LoopUnrolling.cs:57:31:57:47 | { ..., ... } | LoopUnrolling.cs:57:13:57:47 | String[] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:57:33:57:35 | "a" | LoopUnrolling.cs:57:38:57:40 | "b" | semmle.label | successor | -| LoopUnrolling.cs:57:38:57:40 | "b" | LoopUnrolling.cs:57:43:57:45 | "c" | semmle.label | successor | -| LoopUnrolling.cs:57:43:57:45 | "c" | LoopUnrolling.cs:57:31:57:47 | { ..., ... } | semmle.label | successor | -| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | exit M7 (normal) | semmle.label | empty | -| LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | LoopUnrolling.cs:58:22:58:22 | [b (line 55): false] String x | semmle.label | non-empty | -| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:55:10:55:11 | exit M7 (normal) | semmle.label | empty | -| LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | LoopUnrolling.cs:58:22:58:22 | [b (line 55): true] String x | semmle.label | non-empty | -| LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | LoopUnrolling.cs:58:22:58:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:58:22:58:22 | String x | LoopUnrolling.cs:59:9:64:9 | {...} | semmle.label | successor | -| LoopUnrolling.cs:58:22:58:22 | [b (line 55): false] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | semmle.label | successor | -| LoopUnrolling.cs:58:22:58:22 | [b (line 55): true] String x | LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | semmle.label | successor | -| LoopUnrolling.cs:58:27:58:28 | access to local variable xs | LoopUnrolling.cs:58:9:64:9 | [unroll (line 58)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:59:9:64:9 | [b (line 55): false] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:59:9:64:9 | [b (line 55): true] {...} | LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:59:9:64:9 | {...} | LoopUnrolling.cs:60:13:61:37 | if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:60:13:61:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): false] access to parameter b | semmle.label | successor | -| LoopUnrolling.cs:60:13:61:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | semmle.label | successor | -| LoopUnrolling.cs:60:13:61:37 | if (...) ... | LoopUnrolling.cs:60:17:60:17 | access to parameter b | semmle.label | successor | -| 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 (...) ... | semmle.label | false | -| LoopUnrolling.cs:60:17:60:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | semmle.label | true | -| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | semmle.label | true | -| LoopUnrolling.cs:60:17:60:17 | access to parameter b | LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | semmle.label | false | -| LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:61:17:61:37 | [b (line 55): true] ...; | LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:61:35:61:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:61:17:61:36 | [b (line 55): true] call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:62:13:63:37 | [b (line 55): false] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | semmle.label | successor | -| LoopUnrolling.cs:62:13:63:37 | [b (line 55): true] if (...) ... | LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | semmle.label | successor | -| LoopUnrolling.cs:62:17:62:17 | [b (line 55): false] access to parameter b | LoopUnrolling.cs:58:9:64:9 | [b (line 55): false] foreach (... ... in ...) ... | semmle.label | false | -| LoopUnrolling.cs:62:17:62:17 | [b (line 55): true] access to parameter b | LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | semmle.label | true | -| LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | LoopUnrolling.cs:58:9:64:9 | [b (line 55): true] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:63:17:63:37 | [b (line 55): true] ...; | LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:63:35:63:35 | [b (line 55): true] access to local variable x | LoopUnrolling.cs:63:17:63:36 | [b (line 55): true] call to method WriteLine | semmle.label | successor | -| LoopUnrolling.cs:67:10:67:11 | enter M8 | LoopUnrolling.cs:68:5:74:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:67:10:67:11 | exit M8 (normal) | LoopUnrolling.cs:67:10:67:11 | exit M8 | semmle.label | successor | -| LoopUnrolling.cs:68:5:74:5 | {...} | LoopUnrolling.cs:69:9:70:19 | if (...) ... | semmle.label | successor | -| LoopUnrolling.cs:69:9:70:19 | if (...) ... | LoopUnrolling.cs:69:14:69:17 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:69:13:69:23 | [false] !... | LoopUnrolling.cs:71:9:71:21 | ...; | semmle.label | false | -| LoopUnrolling.cs:69:13:69:23 | [true] !... | LoopUnrolling.cs:70:13:70:19 | return ...; | semmle.label | true | -| LoopUnrolling.cs:69:14:69:17 | access to parameter args | LoopUnrolling.cs:69:14:69:23 | call to method Any | semmle.label | successor | -| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:13:69:23 | [false] !... | semmle.label | true | -| LoopUnrolling.cs:69:14:69:23 | call to method Any | LoopUnrolling.cs:69:13:69:23 | [true] !... | semmle.label | false | -| LoopUnrolling.cs:70:13:70:19 | return ...; | LoopUnrolling.cs:67:10:67:11 | exit M8 (normal) | semmle.label | return | -| LoopUnrolling.cs:71:9:71:12 | access to parameter args | LoopUnrolling.cs:71:9:71:20 | call to method Clear | semmle.label | successor | -| LoopUnrolling.cs:71:9:71:20 | call to method Clear | LoopUnrolling.cs:72:29:72:32 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:71:9:71:21 | ...; | LoopUnrolling.cs:71:9:71:12 | access to parameter args | semmle.label | successor | -| LoopUnrolling.cs:72:9:73:35 | [skip (line 72)] foreach (... ... in ...) ... | LoopUnrolling.cs:67:10:67:11 | exit M8 (normal) | semmle.label | empty | -| LoopUnrolling.cs:72:29:72:32 | access to parameter args | LoopUnrolling.cs:72:9:73:35 | [skip (line 72)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:76:10:76:11 | enter M9 | LoopUnrolling.cs:77:5:83:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:76:10:76:11 | exit M9 (normal) | LoopUnrolling.cs:76:10:76:11 | exit M9 | semmle.label | successor | -| LoopUnrolling.cs:77:5:83:5 | {...} | LoopUnrolling.cs:78:9:78:34 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:78:9:78:34 | ... ...; | LoopUnrolling.cs:78:29:78:29 | 2 | semmle.label | successor | -| LoopUnrolling.cs:78:13:78:33 | String[,] xs = ... | LoopUnrolling.cs:79:27:79:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:78:18:78:33 | array creation of type String[,] | LoopUnrolling.cs:78:13:78:33 | String[,] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:78:29:78:29 | 2 | LoopUnrolling.cs:78:32:78:32 | 0 | semmle.label | successor | -| LoopUnrolling.cs:78:32:78:32 | 0 | LoopUnrolling.cs:78:18:78:33 | array creation of type String[,] | semmle.label | successor | -| LoopUnrolling.cs:79:9:82:9 | [skip (line 79)] foreach (... ... in ...) ... | LoopUnrolling.cs:76:10:76:11 | exit M9 (normal) | semmle.label | empty | -| LoopUnrolling.cs:79:27:79:28 | access to local variable xs | LoopUnrolling.cs:79:9:82:9 | [skip (line 79)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:85:10:85:12 | enter M10 | LoopUnrolling.cs:86:5:92:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:85:10:85:12 | exit M10 (normal) | LoopUnrolling.cs:85:10:85:12 | exit M10 | semmle.label | successor | -| LoopUnrolling.cs:86:5:92:5 | {...} | LoopUnrolling.cs:87:9:87:34 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:87:9:87:34 | ... ...; | LoopUnrolling.cs:87:29:87:29 | 0 | semmle.label | successor | -| LoopUnrolling.cs:87:13:87:33 | String[,] xs = ... | LoopUnrolling.cs:88:27:88:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:87:18:87:33 | array creation of type String[,] | LoopUnrolling.cs:87:13:87:33 | String[,] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:87:29:87:29 | 0 | LoopUnrolling.cs:87:32:87:32 | 2 | semmle.label | successor | -| LoopUnrolling.cs:87:32:87:32 | 2 | LoopUnrolling.cs:87:18:87:33 | array creation of type String[,] | semmle.label | successor | -| LoopUnrolling.cs:88:9:91:9 | [skip (line 88)] foreach (... ... in ...) ... | LoopUnrolling.cs:85:10:85:12 | exit M10 (normal) | semmle.label | empty | -| LoopUnrolling.cs:88:27:88:28 | access to local variable xs | LoopUnrolling.cs:88:9:91:9 | [skip (line 88)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:94:10:94:12 | enter M11 | LoopUnrolling.cs:95:5:101:5 | {...} | semmle.label | successor | -| LoopUnrolling.cs:94:10:94:12 | exit M11 (normal) | LoopUnrolling.cs:94:10:94:12 | exit M11 | semmle.label | successor | -| LoopUnrolling.cs:95:5:101:5 | {...} | LoopUnrolling.cs:96:9:96:34 | ... ...; | semmle.label | successor | -| LoopUnrolling.cs:96:9:96:34 | ... ...; | LoopUnrolling.cs:96:29:96:29 | 2 | semmle.label | successor | -| LoopUnrolling.cs:96:13:96:33 | String[,] xs = ... | LoopUnrolling.cs:97:27:97:28 | access to local variable xs | semmle.label | successor | -| LoopUnrolling.cs:96:18:96:33 | array creation of type String[,] | LoopUnrolling.cs:96:13:96:33 | String[,] xs = ... | semmle.label | successor | -| LoopUnrolling.cs:96:29:96:29 | 2 | LoopUnrolling.cs:96:32:96:32 | 2 | semmle.label | successor | -| LoopUnrolling.cs:96:32:96:32 | 2 | LoopUnrolling.cs:96:18:96:33 | array creation of type String[,] | semmle.label | successor | -| LoopUnrolling.cs:97:9:100:9 | [unroll (line 97)] foreach (... ... in ...) ... | LoopUnrolling.cs:97:22:97:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:97:9:100:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:94:10:94:12 | exit M11 (normal) | semmle.label | empty | -| LoopUnrolling.cs:97:9:100:9 | foreach (... ... in ...) ... | LoopUnrolling.cs:97:22:97:22 | String x | semmle.label | non-empty | -| LoopUnrolling.cs:97:22:97:22 | String x | LoopUnrolling.cs:98:9:100:9 | {...} | semmle.label | successor | -| LoopUnrolling.cs:97:27:97:28 | access to local variable xs | LoopUnrolling.cs:97:9:100:9 | [unroll (line 97)] foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:98:9:100:9 | {...} | LoopUnrolling.cs:99:13:99:33 | ...; | semmle.label | successor | -| LoopUnrolling.cs:99:13:99:32 | call to method WriteLine | LoopUnrolling.cs:97:9:100:9 | foreach (... ... in ...) ... | semmle.label | successor | -| LoopUnrolling.cs:99:13:99:33 | ...; | LoopUnrolling.cs:99:31:99:31 | access to local variable x | semmle.label | successor | -| LoopUnrolling.cs:99:31:99:31 | access to local variable x | LoopUnrolling.cs:99:13:99:32 | call to method WriteLine | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | enter get_P1 | MultiImplementationA.cs:6:28:6:31 | null | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | enter get_P1 | MultiImplementationB.cs:3:22:3:22 | 0 | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | exit get_P1 (abnormal) | MultiImplementationA.cs:6:22:6:31 | exit get_P1 | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | exit get_P1 (abnormal) | MultiImplementationB.cs:3:22:3:22 | exit get_P1 | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | exit get_P1 (normal) | MultiImplementationA.cs:6:22:6:31 | exit get_P1 | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | exit get_P1 (normal) | MultiImplementationB.cs:3:22:3:22 | exit get_P1 | semmle.label | successor | -| MultiImplementationA.cs:6:22:6:31 | throw ... | MultiImplementationA.cs:6:22:6:31 | exit get_P1 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:6:22:6:31 | throw ... | MultiImplementationB.cs:3:22:3:22 | exit get_P1 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:6:28:6:31 | null | MultiImplementationA.cs:6:22:6:31 | throw ... | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | enter get_P2 | MultiImplementationA.cs:7:25:7:39 | {...} | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | enter get_P2 | MultiImplementationB.cs:4:25:4:37 | {...} | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | exit get_P2 (abnormal) | MultiImplementationA.cs:7:21:7:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | exit get_P2 (abnormal) | MultiImplementationB.cs:4:21:4:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | exit get_P2 (normal) | MultiImplementationA.cs:7:21:7:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:21:7:23 | exit get_P2 (normal) | MultiImplementationB.cs:4:21:4:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:25:7:39 | {...} | MultiImplementationA.cs:7:33:7:36 | null | semmle.label | successor | -| MultiImplementationA.cs:7:27:7:37 | throw ...; | MultiImplementationA.cs:7:21:7:23 | exit get_P2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:7:27:7:37 | throw ...; | MultiImplementationB.cs:4:21:4:23 | exit get_P2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:7:33:7:36 | null | MultiImplementationA.cs:7:27:7:37 | throw ...; | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | enter set_P2 | MultiImplementationA.cs:7:45:7:59 | {...} | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | enter set_P2 | MultiImplementationB.cs:4:43:4:45 | {...} | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | exit set_P2 (abnormal) | MultiImplementationA.cs:7:41:7:43 | exit set_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | exit set_P2 (abnormal) | MultiImplementationB.cs:4:39:4:41 | exit set_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | exit set_P2 (normal) | MultiImplementationA.cs:7:41:7:43 | exit set_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:41:7:43 | exit set_P2 (normal) | MultiImplementationB.cs:4:39:4:41 | exit set_P2 | semmle.label | successor | -| MultiImplementationA.cs:7:45:7:59 | {...} | MultiImplementationA.cs:7:53:7:56 | null | semmle.label | successor | -| MultiImplementationA.cs:7:47:7:57 | throw ...; | MultiImplementationA.cs:7:41:7:43 | exit set_P2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:7:47:7:57 | throw ...; | MultiImplementationB.cs:4:39:4:41 | exit set_P2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:7:53:7:56 | null | MultiImplementationA.cs:7:47:7:57 | throw ...; | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | enter M | MultiImplementationA.cs:8:29:8:32 | null | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | enter M | MultiImplementationB.cs:5:23:5:23 | 2 | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | exit M (abnormal) | MultiImplementationA.cs:8:16:8:16 | exit M | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | exit M (abnormal) | MultiImplementationB.cs:5:16:5:16 | exit M | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | exit M (normal) | MultiImplementationA.cs:8:16:8:16 | exit M | semmle.label | successor | -| MultiImplementationA.cs:8:16:8:16 | exit M (normal) | MultiImplementationB.cs:5:16:5:16 | exit M | semmle.label | successor | -| MultiImplementationA.cs:8:23:8:32 | throw ... | MultiImplementationA.cs:8:16:8:16 | exit M (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:8:23:8:32 | throw ... | MultiImplementationB.cs:5:16:5:16 | exit M (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:8:29:8:32 | null | MultiImplementationA.cs:8:23:8:32 | throw ... | semmle.label | successor | -| MultiImplementationA.cs:13:16:13:16 | this access | MultiImplementationA.cs:13:20:13:20 | 0 | semmle.label | successor | -| MultiImplementationA.cs:13:16:13:20 | ... = ... | MultiImplementationA.cs:24:16:24:16 | this access | semmle.label | successor | -| MultiImplementationA.cs:13:20:13:20 | 0 | MultiImplementationA.cs:13:16:13:20 | ... = ... | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | access to parameter i | MultiImplementationA.cs:14:31:14:31 | exit get_Item (normal) | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | access to parameter i | MultiImplementationB.cs:12:31:12:40 | exit get_Item (normal) | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | enter get_Item | MultiImplementationA.cs:14:31:14:31 | access to parameter i | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | enter get_Item | MultiImplementationB.cs:12:37:12:40 | null | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | exit get_Item (abnormal) | MultiImplementationA.cs:14:31:14:31 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | exit get_Item (abnormal) | MultiImplementationB.cs:12:31:12:40 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | exit get_Item (normal) | MultiImplementationA.cs:14:31:14:31 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:14:31:14:31 | exit get_Item (normal) | MultiImplementationB.cs:12:31:12:40 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | enter get_Item | MultiImplementationA.cs:15:40:15:52 | {...} | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | enter get_Item | MultiImplementationB.cs:13:40:13:54 | {...} | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | exit get_Item (abnormal) | MultiImplementationA.cs:15:36:15:38 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | exit get_Item (abnormal) | MultiImplementationB.cs:13:36:13:38 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | exit get_Item (normal) | MultiImplementationA.cs:15:36:15:38 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:15:36:15:38 | exit get_Item (normal) | MultiImplementationB.cs:13:36:13:38 | exit get_Item | semmle.label | successor | -| MultiImplementationA.cs:15:40:15:52 | {...} | MultiImplementationA.cs:15:49:15:49 | access to parameter s | semmle.label | successor | -| MultiImplementationA.cs:15:42:15:50 | return ...; | MultiImplementationA.cs:15:36:15:38 | exit get_Item (normal) | semmle.label | return | -| MultiImplementationA.cs:15:42:15:50 | return ...; | MultiImplementationB.cs:13:36:13:38 | exit get_Item (normal) | semmle.label | return | -| MultiImplementationA.cs:15:49:15:49 | access to parameter s | MultiImplementationA.cs:15:42:15:50 | return ...; | semmle.label | successor | -| MultiImplementationA.cs:15:54:15:56 | enter set_Item | MultiImplementationA.cs:15:58:15:60 | {...} | semmle.label | successor | -| MultiImplementationA.cs:15:54:15:56 | enter set_Item | MultiImplementationB.cs:13:60:13:62 | {...} | semmle.label | successor | -| MultiImplementationA.cs:15:54:15:56 | exit set_Item (normal) | MultiImplementationA.cs:15:54:15:56 | exit set_Item | semmle.label | successor | -| MultiImplementationA.cs:15:54:15:56 | exit set_Item (normal) | MultiImplementationB.cs:13:56:13:58 | exit set_Item | semmle.label | successor | -| MultiImplementationA.cs:15:58:15:60 | {...} | MultiImplementationA.cs:15:54:15:56 | exit set_Item (normal) | semmle.label | successor | -| MultiImplementationA.cs:15:58:15:60 | {...} | MultiImplementationB.cs:13:56:13:58 | exit set_Item (normal) | semmle.label | successor | -| MultiImplementationA.cs:16:17:16:18 | enter M1 | MultiImplementationA.cs:17:5:19:5 | {...} | semmle.label | successor | -| MultiImplementationA.cs:16:17:16:18 | enter M1 | MultiImplementationB.cs:15:5:17:5 | {...} | semmle.label | successor | -| MultiImplementationA.cs:16:17:16:18 | exit M1 (normal) | MultiImplementationA.cs:16:17:16:18 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:16:17:16:18 | exit M1 (normal) | MultiImplementationB.cs:14:17:14:18 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:17:5:19:5 | {...} | MultiImplementationA.cs:18:9:18:22 | M2(...) | semmle.label | successor | -| MultiImplementationA.cs:18:9:18:22 | M2(...) | MultiImplementationA.cs:16:17:16:18 | exit M1 (normal) | semmle.label | successor | -| MultiImplementationA.cs:18:9:18:22 | M2(...) | MultiImplementationB.cs:14:17:14:18 | exit M1 (normal) | semmle.label | successor | -| MultiImplementationA.cs:18:9:18:22 | enter M2 | MultiImplementationA.cs:18:21:18:21 | 0 | semmle.label | successor | -| MultiImplementationA.cs:18:9:18:22 | exit M2 (normal) | MultiImplementationA.cs:18:9:18:22 | exit M2 | semmle.label | successor | -| MultiImplementationA.cs:18:21:18:21 | 0 | MultiImplementationA.cs:18:9:18:22 | exit M2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | call to constructor Object | MultiImplementationA.cs:13:16:13:16 | this access | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | enter C2 | MultiImplementationA.cs:20:12:20:13 | call to constructor Object | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | enter C2 | MultiImplementationB.cs:18:12:18:13 | call to constructor Object | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | exit C2 (abnormal) | MultiImplementationA.cs:20:12:20:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | exit C2 (abnormal) | MultiImplementationB.cs:18:12:18:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | exit C2 (normal) | MultiImplementationA.cs:20:12:20:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:20:12:20:13 | exit C2 (normal) | MultiImplementationB.cs:18:12:18:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:20:22:20:31 | {...} | MultiImplementationA.cs:20:24:20:29 | ...; | semmle.label | successor | -| MultiImplementationA.cs:20:24:20:24 | this access | MultiImplementationA.cs:20:28:20:28 | access to parameter i | semmle.label | successor | -| MultiImplementationA.cs:20:24:20:28 | ... = ... | MultiImplementationA.cs:20:12:20:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:20:24:20:28 | ... = ... | MultiImplementationB.cs:18:12:18:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:20:24:20:29 | ...; | MultiImplementationA.cs:20:24:20:24 | this access | semmle.label | successor | -| MultiImplementationA.cs:20:28:20:28 | access to parameter i | MultiImplementationA.cs:20:24:20:28 | ... = ... | semmle.label | successor | -| MultiImplementationA.cs:21:12:21:13 | enter C2 | MultiImplementationA.cs:21:24:21:24 | 0 | semmle.label | successor | -| MultiImplementationA.cs:21:12:21:13 | enter C2 | MultiImplementationB.cs:19:24:19:24 | 1 | semmle.label | successor | -| MultiImplementationA.cs:21:12:21:13 | exit C2 (normal) | MultiImplementationA.cs:21:12:21:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:21:12:21:13 | exit C2 (normal) | MultiImplementationB.cs:19:12:19:13 | exit C2 | semmle.label | successor | -| MultiImplementationA.cs:21:19:21:22 | call to constructor C2 | MultiImplementationA.cs:21:27:21:29 | {...} | semmle.label | successor | -| MultiImplementationA.cs:21:24:21:24 | 0 | MultiImplementationA.cs:21:19:21:22 | call to constructor C2 | semmle.label | successor | -| MultiImplementationA.cs:21:27:21:29 | {...} | MultiImplementationA.cs:21:12:21:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:21:27:21:29 | {...} | MultiImplementationB.cs:19:12:19:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | enter ~C2 | MultiImplementationA.cs:22:11:22:13 | {...} | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | enter ~C2 | MultiImplementationB.cs:20:11:20:25 | {...} | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | exit ~C2 (abnormal) | MultiImplementationA.cs:22:6:22:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | exit ~C2 (abnormal) | MultiImplementationB.cs:20:6:20:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | exit ~C2 (normal) | MultiImplementationA.cs:22:6:22:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationA.cs:22:6:22:7 | exit ~C2 (normal) | MultiImplementationB.cs:20:6:20:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationA.cs:22:11:22:13 | {...} | MultiImplementationA.cs:22:6:22:7 | exit ~C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:22:11:22:13 | {...} | MultiImplementationB.cs:20:6:20:7 | exit ~C2 (normal) | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | enter implicit conversion | MultiImplementationA.cs:23:50:23:53 | null | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | enter implicit conversion | MultiImplementationB.cs:21:56:21:59 | null | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (abnormal) | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (abnormal) | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (normal) | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (normal) | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationA.cs:23:50:23:53 | null | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (normal) | semmle.label | successor | -| MultiImplementationA.cs:23:50:23:53 | null | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (normal) | semmle.label | successor | -| MultiImplementationA.cs:24:16:24:16 | access to property P | MultiImplementationA.cs:24:32:24:34 | ... = ... | semmle.label | successor | -| MultiImplementationA.cs:24:16:24:16 | this access | MultiImplementationA.cs:24:34:24:34 | 0 | semmle.label | successor | -| MultiImplementationA.cs:24:32:24:34 | ... = ... | MultiImplementationA.cs:20:22:20:31 | {...} | semmle.label | successor | -| MultiImplementationA.cs:24:34:24:34 | 0 | MultiImplementationA.cs:24:16:24:16 | access to property P | semmle.label | successor | -| MultiImplementationA.cs:30:21:30:23 | enter get_P3 | MultiImplementationA.cs:30:34:30:37 | null | semmle.label | successor | -| MultiImplementationA.cs:30:21:30:23 | exit get_P3 (abnormal) | MultiImplementationA.cs:30:21:30:23 | exit get_P3 | semmle.label | successor | -| MultiImplementationA.cs:30:21:30:23 | exit get_P3 (abnormal) | MultiImplementationB.cs:27:21:27:23 | exit get_P3 | semmle.label | successor | -| MultiImplementationA.cs:30:28:30:37 | throw ... | MultiImplementationA.cs:30:21:30:23 | exit get_P3 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:30:28:30:37 | throw ... | MultiImplementationB.cs:27:21:27:23 | exit get_P3 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:30:34:30:37 | null | MultiImplementationA.cs:30:28:30:37 | throw ... | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | enter M1 | MultiImplementationA.cs:36:14:36:28 | {...} | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | enter M1 | MultiImplementationB.cs:32:17:32:17 | 0 | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | exit M1 (abnormal) | MultiImplementationA.cs:36:9:36:10 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | exit M1 (abnormal) | MultiImplementationB.cs:32:9:32:10 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | exit M1 (normal) | MultiImplementationA.cs:36:9:36:10 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:36:9:36:10 | exit M1 (normal) | MultiImplementationB.cs:32:9:32:10 | exit M1 | semmle.label | successor | -| MultiImplementationA.cs:36:14:36:28 | {...} | MultiImplementationA.cs:36:22:36:25 | null | semmle.label | successor | -| MultiImplementationA.cs:36:16:36:26 | throw ...; | MultiImplementationA.cs:36:9:36:10 | exit M1 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:36:16:36:26 | throw ...; | MultiImplementationB.cs:32:9:32:10 | exit M1 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:36:22:36:25 | null | MultiImplementationA.cs:36:16:36:26 | throw ...; | semmle.label | successor | -| MultiImplementationA.cs:37:9:37:10 | enter M2 | MultiImplementationA.cs:37:14:37:28 | {...} | semmle.label | successor | -| MultiImplementationA.cs:37:9:37:10 | exit M2 (abnormal) | MultiImplementationA.cs:37:9:37:10 | exit M2 | semmle.label | successor | -| MultiImplementationA.cs:37:14:37:28 | {...} | MultiImplementationA.cs:37:22:37:25 | null | semmle.label | successor | -| MultiImplementationA.cs:37:16:37:26 | throw ...; | MultiImplementationA.cs:37:9:37:10 | exit M2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationA.cs:37:22:37:25 | null | MultiImplementationA.cs:37:16:37:26 | throw ...; | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | 0 | MultiImplementationA.cs:6:22:6:31 | exit get_P1 (normal) | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | 0 | MultiImplementationB.cs:3:22:3:22 | exit get_P1 (normal) | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | enter get_P1 | MultiImplementationA.cs:6:28:6:31 | null | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | enter get_P1 | MultiImplementationB.cs:3:22:3:22 | 0 | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | exit get_P1 (abnormal) | MultiImplementationA.cs:6:22:6:31 | exit get_P1 | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | exit get_P1 (abnormal) | MultiImplementationB.cs:3:22:3:22 | exit get_P1 | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | exit get_P1 (normal) | MultiImplementationA.cs:6:22:6:31 | exit get_P1 | semmle.label | successor | -| MultiImplementationB.cs:3:22:3:22 | exit get_P1 (normal) | MultiImplementationB.cs:3:22:3:22 | exit get_P1 | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | enter get_P2 | MultiImplementationA.cs:7:25:7:39 | {...} | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | enter get_P2 | MultiImplementationB.cs:4:25:4:37 | {...} | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | exit get_P2 (abnormal) | MultiImplementationA.cs:7:21:7:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | exit get_P2 (abnormal) | MultiImplementationB.cs:4:21:4:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | exit get_P2 (normal) | MultiImplementationA.cs:7:21:7:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:21:4:23 | exit get_P2 (normal) | MultiImplementationB.cs:4:21:4:23 | exit get_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:25:4:37 | {...} | MultiImplementationB.cs:4:34:4:34 | 1 | semmle.label | successor | -| MultiImplementationB.cs:4:27:4:35 | return ...; | MultiImplementationA.cs:7:21:7:23 | exit get_P2 (normal) | semmle.label | return | -| MultiImplementationB.cs:4:27:4:35 | return ...; | MultiImplementationB.cs:4:21:4:23 | exit get_P2 (normal) | semmle.label | return | -| MultiImplementationB.cs:4:34:4:34 | 1 | MultiImplementationB.cs:4:27:4:35 | return ...; | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | enter set_P2 | MultiImplementationA.cs:7:45:7:59 | {...} | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | enter set_P2 | MultiImplementationB.cs:4:43:4:45 | {...} | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | exit set_P2 (abnormal) | MultiImplementationA.cs:7:41:7:43 | exit set_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | exit set_P2 (abnormal) | MultiImplementationB.cs:4:39:4:41 | exit set_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | exit set_P2 (normal) | MultiImplementationA.cs:7:41:7:43 | exit set_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:39:4:41 | exit set_P2 (normal) | MultiImplementationB.cs:4:39:4:41 | exit set_P2 | semmle.label | successor | -| MultiImplementationB.cs:4:43:4:45 | {...} | MultiImplementationA.cs:7:41:7:43 | exit set_P2 (normal) | semmle.label | successor | -| MultiImplementationB.cs:4:43:4:45 | {...} | MultiImplementationB.cs:4:39:4:41 | exit set_P2 (normal) | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | enter M | MultiImplementationA.cs:8:29:8:32 | null | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | enter M | MultiImplementationB.cs:5:23:5:23 | 2 | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | exit M (abnormal) | MultiImplementationA.cs:8:16:8:16 | exit M | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | exit M (abnormal) | MultiImplementationB.cs:5:16:5:16 | exit M | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | exit M (normal) | MultiImplementationA.cs:8:16:8:16 | exit M | semmle.label | successor | -| MultiImplementationB.cs:5:16:5:16 | exit M (normal) | MultiImplementationB.cs:5:16:5:16 | exit M | semmle.label | successor | -| MultiImplementationB.cs:5:23:5:23 | 2 | MultiImplementationA.cs:8:16:8:16 | exit M (normal) | semmle.label | successor | -| MultiImplementationB.cs:5:23:5:23 | 2 | MultiImplementationB.cs:5:16:5:16 | exit M (normal) | semmle.label | successor | -| MultiImplementationB.cs:11:16:11:16 | this access | MultiImplementationB.cs:11:20:11:20 | 1 | semmle.label | successor | -| MultiImplementationB.cs:11:16:11:20 | ... = ... | MultiImplementationB.cs:22:16:22:16 | this access | semmle.label | successor | -| MultiImplementationB.cs:11:20:11:20 | 1 | MultiImplementationB.cs:11:16:11:20 | ... = ... | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | enter get_Item | MultiImplementationA.cs:14:31:14:31 | access to parameter i | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | enter get_Item | MultiImplementationB.cs:12:37:12:40 | null | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | exit get_Item (abnormal) | MultiImplementationA.cs:14:31:14:31 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | exit get_Item (abnormal) | MultiImplementationB.cs:12:31:12:40 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | exit get_Item (normal) | MultiImplementationA.cs:14:31:14:31 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | exit get_Item (normal) | MultiImplementationB.cs:12:31:12:40 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:12:31:12:40 | throw ... | MultiImplementationA.cs:14:31:14:31 | exit get_Item (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:12:31:12:40 | throw ... | MultiImplementationB.cs:12:31:12:40 | exit get_Item (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:12:37:12:40 | null | MultiImplementationB.cs:12:31:12:40 | throw ... | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | enter get_Item | MultiImplementationA.cs:15:40:15:52 | {...} | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | enter get_Item | MultiImplementationB.cs:13:40:13:54 | {...} | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | exit get_Item (abnormal) | MultiImplementationA.cs:15:36:15:38 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | exit get_Item (abnormal) | MultiImplementationB.cs:13:36:13:38 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | exit get_Item (normal) | MultiImplementationA.cs:15:36:15:38 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:13:36:13:38 | exit get_Item (normal) | MultiImplementationB.cs:13:36:13:38 | exit get_Item | semmle.label | successor | -| MultiImplementationB.cs:13:40:13:54 | {...} | MultiImplementationB.cs:13:48:13:51 | null | semmle.label | successor | -| MultiImplementationB.cs:13:42:13:52 | throw ...; | MultiImplementationA.cs:15:36:15:38 | exit get_Item (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:13:42:13:52 | throw ...; | MultiImplementationB.cs:13:36:13:38 | exit get_Item (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:13:48:13:51 | null | MultiImplementationB.cs:13:42:13:52 | throw ...; | semmle.label | successor | -| MultiImplementationB.cs:13:56:13:58 | enter set_Item | MultiImplementationA.cs:15:58:15:60 | {...} | semmle.label | successor | -| MultiImplementationB.cs:13:56:13:58 | enter set_Item | MultiImplementationB.cs:13:60:13:62 | {...} | semmle.label | successor | -| MultiImplementationB.cs:13:56:13:58 | exit set_Item (normal) | MultiImplementationA.cs:15:54:15:56 | exit set_Item | semmle.label | successor | -| MultiImplementationB.cs:13:56:13:58 | exit set_Item (normal) | MultiImplementationB.cs:13:56:13:58 | exit set_Item | semmle.label | successor | -| MultiImplementationB.cs:13:60:13:62 | {...} | MultiImplementationA.cs:15:54:15:56 | exit set_Item (normal) | semmle.label | successor | -| MultiImplementationB.cs:13:60:13:62 | {...} | MultiImplementationB.cs:13:56:13:58 | exit set_Item (normal) | semmle.label | successor | -| MultiImplementationB.cs:14:17:14:18 | enter M1 | MultiImplementationA.cs:17:5:19:5 | {...} | semmle.label | successor | -| MultiImplementationB.cs:14:17:14:18 | enter M1 | MultiImplementationB.cs:15:5:17:5 | {...} | semmle.label | successor | -| MultiImplementationB.cs:14:17:14:18 | exit M1 (normal) | MultiImplementationA.cs:16:17:16:18 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:14:17:14:18 | exit M1 (normal) | MultiImplementationB.cs:14:17:14:18 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:15:5:17:5 | {...} | MultiImplementationB.cs:16:9:16:31 | M2(...) | semmle.label | successor | -| MultiImplementationB.cs:16:9:16:31 | M2(...) | MultiImplementationA.cs:16:17:16:18 | exit M1 (normal) | semmle.label | successor | -| MultiImplementationB.cs:16:9:16:31 | M2(...) | MultiImplementationB.cs:14:17:14:18 | exit M1 (normal) | semmle.label | successor | -| MultiImplementationB.cs:16:9:16:31 | enter M2 | MultiImplementationB.cs:16:27:16:30 | null | semmle.label | successor | -| MultiImplementationB.cs:16:9:16:31 | exit M2 (abnormal) | MultiImplementationB.cs:16:9:16:31 | exit M2 | semmle.label | successor | -| MultiImplementationB.cs:16:21:16:30 | throw ... | MultiImplementationB.cs:16:9:16:31 | exit M2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:16:27:16:30 | null | MultiImplementationB.cs:16:21:16:30 | throw ... | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | call to constructor Object | MultiImplementationB.cs:11:16:11:16 | this access | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | enter C2 | MultiImplementationA.cs:20:12:20:13 | call to constructor Object | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | enter C2 | MultiImplementationB.cs:18:12:18:13 | call to constructor Object | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | exit C2 (abnormal) | MultiImplementationA.cs:20:12:20:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | exit C2 (abnormal) | MultiImplementationB.cs:18:12:18:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | exit C2 (normal) | MultiImplementationA.cs:20:12:20:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:18:12:18:13 | exit C2 (normal) | MultiImplementationB.cs:18:12:18:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:18:22:18:36 | {...} | MultiImplementationB.cs:18:30:18:33 | null | semmle.label | successor | -| MultiImplementationB.cs:18:24:18:34 | throw ...; | MultiImplementationA.cs:20:12:20:13 | exit C2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:18:24:18:34 | throw ...; | MultiImplementationB.cs:18:12:18:13 | exit C2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:18:30:18:33 | null | MultiImplementationB.cs:18:24:18:34 | throw ...; | semmle.label | successor | -| MultiImplementationB.cs:19:12:19:13 | enter C2 | MultiImplementationA.cs:21:24:21:24 | 0 | semmle.label | successor | -| MultiImplementationB.cs:19:12:19:13 | enter C2 | MultiImplementationB.cs:19:24:19:24 | 1 | semmle.label | successor | -| MultiImplementationB.cs:19:12:19:13 | exit C2 (normal) | MultiImplementationA.cs:21:12:21:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:19:12:19:13 | exit C2 (normal) | MultiImplementationB.cs:19:12:19:13 | exit C2 | semmle.label | successor | -| MultiImplementationB.cs:19:19:19:22 | call to constructor C2 | MultiImplementationB.cs:19:27:19:29 | {...} | semmle.label | successor | -| MultiImplementationB.cs:19:24:19:24 | 1 | MultiImplementationB.cs:19:19:19:22 | call to constructor C2 | semmle.label | successor | -| MultiImplementationB.cs:19:27:19:29 | {...} | MultiImplementationA.cs:21:12:21:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationB.cs:19:27:19:29 | {...} | MultiImplementationB.cs:19:12:19:13 | exit C2 (normal) | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | enter ~C2 | MultiImplementationA.cs:22:11:22:13 | {...} | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | enter ~C2 | MultiImplementationB.cs:20:11:20:25 | {...} | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | exit ~C2 (abnormal) | MultiImplementationA.cs:22:6:22:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | exit ~C2 (abnormal) | MultiImplementationB.cs:20:6:20:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | exit ~C2 (normal) | MultiImplementationA.cs:22:6:22:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationB.cs:20:6:20:7 | exit ~C2 (normal) | MultiImplementationB.cs:20:6:20:7 | exit ~C2 | semmle.label | successor | -| MultiImplementationB.cs:20:11:20:25 | {...} | MultiImplementationB.cs:20:19:20:22 | null | semmle.label | successor | -| MultiImplementationB.cs:20:13:20:23 | throw ...; | MultiImplementationA.cs:22:6:22:7 | exit ~C2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:20:13:20:23 | throw ...; | MultiImplementationB.cs:20:6:20:7 | exit ~C2 (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:20:19:20:22 | null | MultiImplementationB.cs:20:13:20:23 | throw ...; | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | enter implicit conversion | MultiImplementationA.cs:23:50:23:53 | null | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | enter implicit conversion | MultiImplementationB.cs:21:56:21:59 | null | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (abnormal) | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (abnormal) | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (normal) | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (normal) | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion | semmle.label | successor | -| MultiImplementationB.cs:21:50:21:59 | throw ... | MultiImplementationA.cs:23:28:23:35 | exit implicit conversion (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:21:50:21:59 | throw ... | MultiImplementationB.cs:21:28:21:35 | exit implicit conversion (abnormal) | semmle.label | exception(NullReferenceException) | -| MultiImplementationB.cs:21:56:21:59 | null | MultiImplementationB.cs:21:50:21:59 | throw ... | semmle.label | successor | -| MultiImplementationB.cs:22:16:22:16 | access to property P | MultiImplementationB.cs:22:32:22:34 | ... = ... | semmle.label | successor | -| MultiImplementationB.cs:22:16:22:16 | this access | MultiImplementationB.cs:22:34:22:34 | 1 | semmle.label | successor | -| MultiImplementationB.cs:22:32:22:34 | ... = ... | MultiImplementationB.cs:18:22:18:36 | {...} | semmle.label | successor | -| MultiImplementationB.cs:22:34:22:34 | 1 | MultiImplementationB.cs:22:16:22:16 | access to property P | semmle.label | successor | -| MultiImplementationB.cs:27:21:27:23 | enter get_P3 | MultiImplementationA.cs:30:34:30:37 | null | semmle.label | successor | -| MultiImplementationB.cs:27:21:27:23 | exit get_P3 (abnormal) | MultiImplementationA.cs:30:21:30:23 | exit get_P3 | semmle.label | successor | -| MultiImplementationB.cs:27:21:27:23 | exit get_P3 (abnormal) | MultiImplementationB.cs:27:21:27:23 | exit get_P3 | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | enter M1 | MultiImplementationA.cs:36:14:36:28 | {...} | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | enter M1 | MultiImplementationB.cs:32:17:32:17 | 0 | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | exit M1 (abnormal) | MultiImplementationA.cs:36:9:36:10 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | exit M1 (abnormal) | MultiImplementationB.cs:32:9:32:10 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | exit M1 (normal) | MultiImplementationA.cs:36:9:36:10 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:32:9:32:10 | exit M1 (normal) | MultiImplementationB.cs:32:9:32:10 | exit M1 | semmle.label | successor | -| MultiImplementationB.cs:32:17:32:17 | 0 | MultiImplementationA.cs:36:9:36:10 | exit M1 (normal) | semmle.label | successor | -| MultiImplementationB.cs:32:17:32:17 | 0 | MultiImplementationB.cs:32:9:32:10 | exit M1 (normal) | semmle.label | successor | -| NullCoalescing.cs:3:9:3:10 | enter M1 | NullCoalescing.cs:3:23:3:23 | access to parameter i | semmle.label | successor | -| NullCoalescing.cs:3:9:3:10 | exit M1 (normal) | NullCoalescing.cs:3:9:3:10 | exit M1 | semmle.label | successor | -| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:23:3:28 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:3:23:3:23 | access to parameter i | NullCoalescing.cs:3:28:3:28 | 0 | semmle.label | null | -| NullCoalescing.cs:3:23:3:28 | ... ?? ... | NullCoalescing.cs:3:9:3:10 | exit M1 (normal) | semmle.label | successor | -| NullCoalescing.cs:3:28:3:28 | 0 | NullCoalescing.cs:3:23:3:28 | ... ?? ... | semmle.label | successor | -| NullCoalescing.cs:5:9:5:10 | enter M2 | NullCoalescing.cs:5:25:5:25 | access to parameter b | semmle.label | successor | -| NullCoalescing.cs:5:9:5:10 | exit M2 (normal) | NullCoalescing.cs:5:9:5:10 | exit M2 | semmle.label | successor | -| NullCoalescing.cs:5:24:5:43 | ... ? ... : ... | NullCoalescing.cs:5:9:5:10 | exit M2 (normal) | semmle.label | successor | -| NullCoalescing.cs:5:25:5:25 | access to parameter b | NullCoalescing.cs:5:25:5:34 | [false] ... ?? ... | semmle.label | false | -| NullCoalescing.cs:5:25:5:25 | access to parameter b | NullCoalescing.cs:5:25:5:34 | [true] ... ?? ... | semmle.label | true | -| NullCoalescing.cs:5:25:5:25 | access to parameter b | NullCoalescing.cs:5:30:5:34 | false | semmle.label | null | -| NullCoalescing.cs:5:25:5:34 | [false] ... ?? ... | NullCoalescing.cs:5:43:5:43 | 1 | semmle.label | false | -| NullCoalescing.cs:5:25:5:34 | [true] ... ?? ... | NullCoalescing.cs:5:39:5:39 | 0 | semmle.label | true | -| NullCoalescing.cs:5:30:5:34 | false | NullCoalescing.cs:5:25:5:34 | [false] ... ?? ... | semmle.label | false | -| NullCoalescing.cs:5:39:5:39 | 0 | NullCoalescing.cs:5:24:5:43 | ... ? ... : ... | semmle.label | successor | -| NullCoalescing.cs:5:43:5:43 | 1 | NullCoalescing.cs:5:24:5:43 | ... ? ... : ... | semmle.label | successor | -| NullCoalescing.cs:7:12:7:13 | enter M3 | NullCoalescing.cs:7:40:7:41 | access to parameter s1 | semmle.label | successor | -| NullCoalescing.cs:7:12:7:13 | exit M3 (normal) | NullCoalescing.cs:7:12:7:13 | exit M3 | semmle.label | successor | -| NullCoalescing.cs:7:40:7:41 | access to parameter s1 | NullCoalescing.cs:7:40:7:53 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:7:40:7:41 | access to parameter s1 | NullCoalescing.cs:7:46:7:47 | access to parameter s2 | semmle.label | null | -| NullCoalescing.cs:7:40:7:53 | ... ?? ... | NullCoalescing.cs:7:12:7:13 | exit M3 (normal) | semmle.label | successor | -| NullCoalescing.cs:7:46:7:47 | access to parameter s2 | NullCoalescing.cs:7:46:7:53 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:7:46:7:47 | access to parameter s2 | NullCoalescing.cs:7:52:7:53 | "" | semmle.label | null | -| NullCoalescing.cs:7:46:7:53 | ... ?? ... | NullCoalescing.cs:7:40:7:53 | ... ?? ... | semmle.label | successor | -| NullCoalescing.cs:7:52:7:53 | "" | NullCoalescing.cs:7:46:7:53 | ... ?? ... | semmle.label | successor | -| NullCoalescing.cs:9:12:9:13 | enter M4 | NullCoalescing.cs:9:37:9:37 | access to parameter b | semmle.label | successor | -| NullCoalescing.cs:9:12:9:13 | exit M4 (normal) | NullCoalescing.cs:9:12:9:13 | exit M4 | semmle.label | successor | -| NullCoalescing.cs:9:36:9:58 | ... ?? ... | NullCoalescing.cs:9:12:9:13 | exit M4 (normal) | semmle.label | successor | -| NullCoalescing.cs:9:37:9:37 | access to parameter b | NullCoalescing.cs:9:41:9:41 | access to parameter s | semmle.label | true | -| NullCoalescing.cs:9:37:9:37 | access to parameter b | NullCoalescing.cs:9:45:9:45 | access to parameter s | semmle.label | false | -| NullCoalescing.cs:9:37:9:45 | [non-null] ... ? ... : ... | NullCoalescing.cs:9:36:9:58 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:9:37:9:45 | [null] ... ? ... : ... | NullCoalescing.cs:9:51:9:52 | "" | semmle.label | null | -| NullCoalescing.cs:9:41:9:41 | access to parameter s | NullCoalescing.cs:9:37:9:45 | [non-null] ... ? ... : ... | semmle.label | non-null | -| NullCoalescing.cs:9:41:9:41 | access to parameter s | NullCoalescing.cs:9:37:9:45 | [null] ... ? ... : ... | semmle.label | null | -| NullCoalescing.cs:9:45:9:45 | access to parameter s | NullCoalescing.cs:9:37:9:45 | [non-null] ... ? ... : ... | semmle.label | non-null | -| NullCoalescing.cs:9:45:9:45 | access to parameter s | NullCoalescing.cs:9:37:9:45 | [null] ... ? ... : ... | semmle.label | null | -| NullCoalescing.cs:9:51:9:52 | "" | NullCoalescing.cs:9:51:9:58 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:9:51:9:58 | ... ?? ... | NullCoalescing.cs:9:36:9:58 | ... ?? ... | semmle.label | successor | -| NullCoalescing.cs:11:9:11:10 | enter M5 | NullCoalescing.cs:11:44:11:45 | access to parameter b1 | semmle.label | successor | -| NullCoalescing.cs:11:9:11:10 | exit M5 (normal) | NullCoalescing.cs:11:9:11:10 | exit M5 | semmle.label | successor | -| NullCoalescing.cs:11:43:11:68 | ... ? ... : ... | NullCoalescing.cs:11:9:11:10 | exit M5 (normal) | semmle.label | successor | -| NullCoalescing.cs:11:44:11:45 | access to parameter b1 | NullCoalescing.cs:11:44:11:59 | [false] ... ?? ... | semmle.label | false | -| NullCoalescing.cs:11:44:11:45 | access to parameter b1 | NullCoalescing.cs:11:44:11:59 | [true] ... ?? ... | semmle.label | true | -| NullCoalescing.cs:11:44:11:45 | access to parameter b1 | NullCoalescing.cs:11:51:11:52 | access to parameter b2 | semmle.label | null | -| NullCoalescing.cs:11:44:11:59 | [false] ... ?? ... | NullCoalescing.cs:11:68:11:68 | 1 | semmle.label | false | -| NullCoalescing.cs:11:44:11:59 | [true] ... ?? ... | NullCoalescing.cs:11:64:11:64 | 0 | semmle.label | true | -| NullCoalescing.cs:11:51:11:52 | access to parameter b2 | NullCoalescing.cs:11:51:11:58 | [false] ... && ... | semmle.label | false | -| NullCoalescing.cs:11:51:11:52 | access to parameter b2 | NullCoalescing.cs:11:57:11:58 | access to parameter b3 | semmle.label | true | -| NullCoalescing.cs:11:51:11:58 | [false] ... && ... | NullCoalescing.cs:11:44:11:59 | [false] ... ?? ... | semmle.label | false | -| NullCoalescing.cs:11:51:11:58 | [true] ... && ... | NullCoalescing.cs:11:44:11:59 | [true] ... ?? ... | semmle.label | true | -| NullCoalescing.cs:11:57:11:58 | access to parameter b3 | NullCoalescing.cs:11:51:11:58 | [false] ... && ... | semmle.label | false | -| NullCoalescing.cs:11:57:11:58 | access to parameter b3 | NullCoalescing.cs:11:51:11:58 | [true] ... && ... | semmle.label | true | -| NullCoalescing.cs:11:64:11:64 | 0 | NullCoalescing.cs:11:43:11:68 | ... ? ... : ... | semmle.label | successor | -| NullCoalescing.cs:11:68:11:68 | 1 | NullCoalescing.cs:11:43:11:68 | ... ? ... : ... | semmle.label | successor | -| NullCoalescing.cs:13:10:13:11 | enter M6 | NullCoalescing.cs:14:5:18:5 | {...} | semmle.label | successor | -| NullCoalescing.cs:13:10:13:11 | exit M6 (normal) | NullCoalescing.cs:13:10:13:11 | exit M6 | semmle.label | successor | -| NullCoalescing.cs:14:5:18:5 | {...} | NullCoalescing.cs:15:9:15:32 | ... ...; | semmle.label | successor | -| NullCoalescing.cs:15:9:15:32 | ... ...; | NullCoalescing.cs:15:23:15:26 | null | semmle.label | successor | -| NullCoalescing.cs:15:13:15:31 | Int32 j = ... | NullCoalescing.cs:16:9:16:26 | ... ...; | semmle.label | successor | -| NullCoalescing.cs:15:17:15:26 | (...) ... | NullCoalescing.cs:15:31:15:31 | 0 | semmle.label | null | -| NullCoalescing.cs:15:17:15:31 | ... ?? ... | NullCoalescing.cs:15:13:15:31 | Int32 j = ... | semmle.label | successor | -| NullCoalescing.cs:15:23:15:26 | null | NullCoalescing.cs:15:17:15:26 | (...) ... | semmle.label | successor | -| NullCoalescing.cs:15:31:15:31 | 0 | NullCoalescing.cs:15:17:15:31 | ... ?? ... | semmle.label | successor | -| NullCoalescing.cs:16:9:16:26 | ... ...; | NullCoalescing.cs:16:17:16:18 | "" | semmle.label | successor | -| NullCoalescing.cs:16:13:16:25 | String s = ... | NullCoalescing.cs:17:9:17:25 | ...; | semmle.label | successor | -| NullCoalescing.cs:16:17:16:18 | "" | NullCoalescing.cs:16:17:16:25 | ... ?? ... | semmle.label | non-null | -| NullCoalescing.cs:16:17:16:25 | ... ?? ... | NullCoalescing.cs:16:13:16:25 | String s = ... | semmle.label | successor | -| NullCoalescing.cs:17:9:17:24 | ... = ... | NullCoalescing.cs:13:10:13:11 | exit M6 (normal) | semmle.label | successor | -| NullCoalescing.cs:17:9:17:25 | ...; | NullCoalescing.cs:17:19:17:19 | access to parameter i | semmle.label | successor | -| 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 | -| PartialImplementationA.cs:3:12:3:18 | call to constructor Object | PartialImplementationB.cs:3:16:3:16 | this access | semmle.label | successor | -| PartialImplementationA.cs:3:12:3:18 | enter Partial | PartialImplementationA.cs:3:12:3:18 | call to constructor Object | semmle.label | successor | -| PartialImplementationA.cs:3:12:3:18 | exit Partial (normal) | PartialImplementationA.cs:3:12:3:18 | exit Partial | semmle.label | successor | -| PartialImplementationA.cs:3:27:3:29 | {...} | PartialImplementationA.cs:3:12:3:18 | exit Partial (normal) | semmle.label | successor | -| PartialImplementationB.cs:3:16:3:16 | this access | PartialImplementationB.cs:3:20:3:20 | 0 | semmle.label | successor | -| PartialImplementationB.cs:3:16:3:16 | this access | PartialImplementationB.cs:3:20:3:20 | 0 | semmle.label | successor | -| PartialImplementationB.cs:3:16:3:20 | ... = ... | PartialImplementationB.cs:5:16:5:16 | this access | semmle.label | successor | -| PartialImplementationB.cs:3:16:3:20 | ... = ... | PartialImplementationB.cs:5:16:5:16 | this access | semmle.label | successor | -| PartialImplementationB.cs:3:20:3:20 | 0 | PartialImplementationB.cs:3:16:3:20 | ... = ... | semmle.label | successor | -| PartialImplementationB.cs:3:20:3:20 | 0 | PartialImplementationB.cs:3:16:3:20 | ... = ... | semmle.label | successor | -| PartialImplementationB.cs:4:12:4:18 | call to constructor Object | PartialImplementationB.cs:3:16:3:16 | this access | semmle.label | successor | -| PartialImplementationB.cs:4:12:4:18 | enter Partial | PartialImplementationB.cs:4:12:4:18 | call to constructor Object | semmle.label | successor | -| PartialImplementationB.cs:4:12:4:18 | exit Partial (normal) | PartialImplementationB.cs:4:12:4:18 | exit Partial | semmle.label | successor | -| PartialImplementationB.cs:4:22:4:24 | {...} | PartialImplementationB.cs:4:12:4:18 | exit Partial (normal) | semmle.label | successor | -| PartialImplementationB.cs:5:16:5:16 | access to property P | PartialImplementationB.cs:5:32:5:34 | ... = ... | semmle.label | successor | -| PartialImplementationB.cs:5:16:5:16 | access to property P | PartialImplementationB.cs:5:32:5:34 | ... = ... | semmle.label | successor | -| PartialImplementationB.cs:5:16:5:16 | this access | PartialImplementationB.cs:5:34:5:34 | 0 | semmle.label | successor | -| PartialImplementationB.cs:5:16:5:16 | this access | PartialImplementationB.cs:5:34:5:34 | 0 | semmle.label | successor | -| PartialImplementationB.cs:5:32:5:34 | ... = ... | PartialImplementationA.cs:3:27:3:29 | {...} | semmle.label | successor | -| PartialImplementationB.cs:5:32:5:34 | ... = ... | PartialImplementationB.cs:4:22:4:24 | {...} | semmle.label | successor | -| PartialImplementationB.cs:5:34:5:34 | 0 | PartialImplementationB.cs:5:16:5:16 | access to property P | semmle.label | successor | -| PartialImplementationB.cs:5:34:5:34 | 0 | PartialImplementationB.cs:5:16:5:16 | access to property P | 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 | -| 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 | [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 | -| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | semmle.label | successor | -| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | semmle.label | successor | -| 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 | [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 | -| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:13:14:45 | call to method WriteLine | semmle.label | successor | -| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:41:14:42 | access to local variable s1 | semmle.label | successor | -| 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 | [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 | -| Patterns.cs:22:13:22:23 | case ...: | Patterns.cs:22:18:22:22 | "xyz" | semmle.label | successor | -| Patterns.cs:22:18:22:22 | "xyz" | Patterns.cs:23:17:23:22 | break; | semmle.label | match | -| Patterns.cs:22:18:22:22 | "xyz" | Patterns.cs:24:13:24:36 | case ...: | semmle.label | no-match | -| Patterns.cs:23:17:23:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | -| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:24:18:24:23 | Int32 i2 | semmle.label | successor | -| Patterns.cs:24:18:24:23 | Int32 i2 | Patterns.cs:24:30:24:31 | access to local variable i2 | semmle.label | match | -| Patterns.cs:24:18:24:23 | Int32 i2 | Patterns.cs:27:13:27:24 | case ...: | semmle.label | no-match | -| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:24:35:24:35 | 0 | semmle.label | successor | -| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:25:17:25:52 | ...; | semmle.label | true | -| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:27:13:27:24 | case ...: | semmle.label | false | -| Patterns.cs:24:35:24:35 | 0 | Patterns.cs:24:30:24:35 | ... > ... | semmle.label | successor | -| Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:26:17:26:22 | break; | semmle.label | successor | -| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | semmle.label | successor | -| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | semmle.label | successor | -| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | semmle.label | successor | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | semmle.label | successor | -| Patterns.cs:26:17:26:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | -| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | semmle.label | successor | -| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | semmle.label | match | -| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:30:13:30:27 | case ...: | semmle.label | no-match | -| Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:29:17:29:22 | break; | semmle.label | successor | -| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | semmle.label | successor | -| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | semmle.label | successor | -| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | semmle.label | successor | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | semmle.label | successor | -| Patterns.cs:29:17:29:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | -| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | semmle.label | successor | -| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | semmle.label | match | -| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:33:13:33:24 | case ...: | semmle.label | no-match | -| Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:32:17:32:22 | break; | semmle.label | successor | -| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:31:37:31:43 | "string " | semmle.label | successor | -| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:17:31:49 | call to method WriteLine | semmle.label | successor | -| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:45:31:46 | access to local variable s2 | semmle.label | successor | -| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:35:31:48 | $"..." | semmle.label | successor | -| Patterns.cs:32:17:32:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | -| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | semmle.label | successor | -| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:34:17:34:22 | break; | semmle.label | match | -| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:35:13:35:20 | default: | semmle.label | no-match | -| Patterns.cs:34:17:34:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | semmle.label | break | -| Patterns.cs:35:13:35:20 | default: | Patterns.cs:36:17:36:52 | ...; | semmle.label | successor | -| Patterns.cs:36:17:36:51 | call to method WriteLine | Patterns.cs:37:17:37:22 | break; | semmle.label | successor | -| Patterns.cs:36:17:36:52 | ...; | Patterns.cs:36:35:36:50 | "Something else" | semmle.label | successor | -| 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: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 | [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 | [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 | -| 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:18:54:37 | { ... } | semmle.label | no-match | -| Patterns.cs:54:18:54:37 | Patterns u | Patterns.cs:54:33:54:33 | 1 | semmle.label | match | -| Patterns.cs:54:18:54:37 | { ... } | Patterns.cs:54:14:54:37 | not ... | semmle.label | successor | -| Patterns.cs:54:27:54:35 | [match] { ... } | Patterns.cs:54:18:54:37 | { ... } | semmle.label | match | -| Patterns.cs:54:27:54:35 | [no-match] { ... } | Patterns.cs:54:18:54:37 | { ... } | semmle.label | no-match | -| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:27:54:35 | [match] { ... } | semmle.label | match | -| Patterns.cs:54:33:54:33 | 1 | Patterns.cs:54:27:54:35 | [no-match] { ... } | semmle.label | no-match | -| 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 | [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 | [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 | -| 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 | [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 | -| 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 | -| 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 | -| Patterns.cs:93:17:93:19 | enter M10 | Patterns.cs:94:5:99:5 | {...} | semmle.label | successor | -| Patterns.cs:93:17:93:19 | exit M10 (normal) | Patterns.cs:93:17:93:19 | exit M10 | semmle.label | successor | -| Patterns.cs:94:5:99:5 | {...} | Patterns.cs:95:9:98:9 | if (...) ... | semmle.label | successor | -| Patterns.cs:95:9:98:9 | if (...) ... | Patterns.cs:95:13:95:16 | this access | semmle.label | successor | -| Patterns.cs:95:13:95:16 | this access | Patterns.cs:95:29:95:31 | access to constant A | semmle.label | successor | -| Patterns.cs:95:13:95:40 | [false] ... is ... | Patterns.cs:93:17:93:19 | exit M10 (normal) | semmle.label | false | -| Patterns.cs:95:13:95:40 | [true] ... is ... | Patterns.cs:96:9:98:9 | {...} | semmle.label | true | -| Patterns.cs:95:21:95:40 | [match] { ... } | Patterns.cs:95:13:95:40 | [true] ... is ... | semmle.label | match | -| Patterns.cs:95:21:95:40 | [match] { ... } | Patterns.cs:95:21:95:40 | [match] { ... } | semmle.label | match | -| Patterns.cs:95:21:95:40 | [no-match] { ... } | Patterns.cs:95:13:95:40 | [false] ... is ... | semmle.label | no-match | -| Patterns.cs:95:21:95:40 | [no-match] { ... } | Patterns.cs:95:21:95:40 | [no-match] { ... } | semmle.label | no-match | -| Patterns.cs:95:29:95:31 | access to constant A | Patterns.cs:95:29:95:38 | [match] ... or ... | semmle.label | match | -| Patterns.cs:95:29:95:31 | access to constant A | Patterns.cs:95:36:95:38 | access to constant B | semmle.label | no-match | -| Patterns.cs:95:29:95:38 | [match] ... or ... | Patterns.cs:95:21:95:40 | [match] { ... } | semmle.label | match | -| Patterns.cs:95:29:95:38 | [no-match] ... or ... | Patterns.cs:95:21:95:40 | [no-match] { ... } | semmle.label | no-match | -| Patterns.cs:95:36:95:38 | access to constant B | Patterns.cs:95:29:95:38 | [match] ... or ... | semmle.label | match | -| Patterns.cs:95:36:95:38 | access to constant B | Patterns.cs:95:29:95:38 | [no-match] ... or ... | semmle.label | no-match | -| Patterns.cs:96:9:98:9 | {...} | Patterns.cs:97:13:97:39 | ...; | semmle.label | successor | -| Patterns.cs:97:13:97:38 | call to method WriteLine | Patterns.cs:93:17:93:19 | exit M10 (normal) | semmle.label | successor | -| Patterns.cs:97:13:97:39 | ...; | Patterns.cs:97:31:97:37 | "not C" | semmle.label | successor | -| Patterns.cs:97:31:97:37 | "not C" | Patterns.cs:97:13:97:38 | call to method WriteLine | 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 | -| PostDominance.cs:7:9:7:28 | call to method WriteLine | PostDominance.cs:5:10:5:11 | exit M1 (normal) | semmle.label | successor | -| PostDominance.cs:7:9:7:29 | ...; | PostDominance.cs:7:27:7:27 | access to parameter s | semmle.label | successor | -| PostDominance.cs:7:27:7:27 | access to parameter s | PostDominance.cs:7:9:7:28 | call to method WriteLine | semmle.label | successor | -| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:11:5:15:5 | {...} | semmle.label | successor | -| PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | semmle.label | successor | -| 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 | [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 | -| PostDominance.cs:14:27:14:27 | access to parameter s | PostDominance.cs:14:9:14:28 | call to method WriteLine | semmle.label | successor | -| PostDominance.cs:17:10:17:11 | enter M3 | PostDominance.cs:18:5:22:5 | {...} | semmle.label | successor | -| PostDominance.cs:17:10:17:11 | exit M3 (abnormal) | PostDominance.cs:17:10:17:11 | exit M3 | semmle.label | successor | -| PostDominance.cs:17:10:17:11 | exit M3 (normal) | PostDominance.cs:17:10:17:11 | exit M3 | semmle.label | successor | -| 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 | [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 | -| PostDominance.cs:21:9:21:28 | call to method WriteLine | PostDominance.cs:17:10:17:11 | exit M3 (normal) | semmle.label | successor | -| PostDominance.cs:21:9:21:29 | ...; | PostDominance.cs:21:27:21:27 | access to parameter s | semmle.label | successor | -| PostDominance.cs:21:27:21:27 | access to parameter s | PostDominance.cs:21:9:21:28 | call to method WriteLine | semmle.label | successor | -| Qualifiers.cs:7:16:7:21 | enter Method | Qualifiers.cs:7:28:7:31 | null | semmle.label | successor | -| Qualifiers.cs:7:16:7:21 | exit Method (normal) | Qualifiers.cs:7:16:7:21 | exit Method | semmle.label | successor | -| Qualifiers.cs:7:28:7:31 | null | Qualifiers.cs:7:16:7:21 | exit Method (normal) | semmle.label | successor | -| Qualifiers.cs:8:23:8:34 | enter StaticMethod | Qualifiers.cs:8:41:8:44 | null | semmle.label | successor | -| Qualifiers.cs:8:23:8:34 | exit StaticMethod (normal) | Qualifiers.cs:8:23:8:34 | exit StaticMethod | semmle.label | successor | -| Qualifiers.cs:8:41:8:44 | null | Qualifiers.cs:8:23:8:34 | exit StaticMethod (normal) | semmle.label | successor | -| Qualifiers.cs:10:10:10:10 | enter M | Qualifiers.cs:11:5:31:5 | {...} | semmle.label | successor | -| Qualifiers.cs:10:10:10:10 | exit M (normal) | Qualifiers.cs:10:10:10:10 | exit M | semmle.label | successor | -| Qualifiers.cs:11:5:31:5 | {...} | Qualifiers.cs:12:9:12:22 | ... ...; | semmle.label | successor | -| Qualifiers.cs:12:9:12:22 | ... ...; | Qualifiers.cs:12:17:12:21 | this access | semmle.label | successor | -| Qualifiers.cs:12:13:12:21 | Qualifiers q = ... | Qualifiers.cs:13:9:13:21 | ...; | semmle.label | successor | -| Qualifiers.cs:12:17:12:21 | access to field Field | Qualifiers.cs:12:13:12:21 | Qualifiers q = ... | semmle.label | successor | -| Qualifiers.cs:12:17:12:21 | this access | Qualifiers.cs:12:17:12:21 | access to field Field | semmle.label | successor | -| Qualifiers.cs:13:9:13:20 | ... = ... | Qualifiers.cs:14:9:14:21 | ...; | semmle.label | successor | -| Qualifiers.cs:13:9:13:21 | ...; | Qualifiers.cs:13:13:13:20 | this access | semmle.label | successor | -| Qualifiers.cs:13:13:13:20 | access to property Property | Qualifiers.cs:13:9:13:20 | ... = ... | semmle.label | successor | -| Qualifiers.cs:13:13:13:20 | this access | Qualifiers.cs:13:13:13:20 | access to property Property | semmle.label | successor | -| Qualifiers.cs:14:9:14:20 | ... = ... | Qualifiers.cs:16:9:16:23 | ...; | semmle.label | successor | -| Qualifiers.cs:14:9:14:21 | ...; | Qualifiers.cs:14:13:14:20 | this access | semmle.label | successor | -| Qualifiers.cs:14:13:14:20 | call to method Method | Qualifiers.cs:14:9:14:20 | ... = ... | semmle.label | successor | -| Qualifiers.cs:14:13:14:20 | this access | Qualifiers.cs:14:13:14:20 | call to method Method | semmle.label | successor | -| Qualifiers.cs:16:9:16:22 | ... = ... | Qualifiers.cs:17:9:17:26 | ...; | semmle.label | successor | -| Qualifiers.cs:16:9:16:23 | ...; | Qualifiers.cs:16:13:16:16 | this access | semmle.label | successor | -| Qualifiers.cs:16:13:16:16 | this access | Qualifiers.cs:16:13:16:22 | access to field Field | semmle.label | successor | -| Qualifiers.cs:16:13:16:22 | access to field Field | Qualifiers.cs:16:9:16:22 | ... = ... | semmle.label | successor | -| Qualifiers.cs:17:9:17:25 | ... = ... | Qualifiers.cs:18:9:18:26 | ...; | semmle.label | successor | -| Qualifiers.cs:17:9:17:26 | ...; | Qualifiers.cs:17:13:17:16 | this access | semmle.label | successor | -| Qualifiers.cs:17:13:17:16 | this access | Qualifiers.cs:17:13:17:25 | access to property Property | semmle.label | successor | -| Qualifiers.cs:17:13:17:25 | access to property Property | Qualifiers.cs:17:9:17:25 | ... = ... | semmle.label | successor | -| Qualifiers.cs:18:9:18:25 | ... = ... | Qualifiers.cs:20:9:20:24 | ...; | semmle.label | successor | -| Qualifiers.cs:18:9:18:26 | ...; | Qualifiers.cs:18:13:18:16 | this access | semmle.label | successor | -| Qualifiers.cs:18:13:18:16 | this access | Qualifiers.cs:18:13:18:25 | call to method Method | semmle.label | successor | -| Qualifiers.cs:18:13:18:25 | call to method Method | Qualifiers.cs:18:9:18:25 | ... = ... | semmle.label | successor | -| Qualifiers.cs:20:9:20:23 | ... = ... | Qualifiers.cs:21:9:21:27 | ...; | semmle.label | successor | -| Qualifiers.cs:20:9:20:24 | ...; | Qualifiers.cs:20:13:20:23 | access to field StaticField | semmle.label | successor | -| Qualifiers.cs:20:13:20:23 | access to field StaticField | Qualifiers.cs:20:9:20:23 | ... = ... | semmle.label | successor | -| Qualifiers.cs:21:9:21:26 | ... = ... | Qualifiers.cs:22:9:22:27 | ...; | semmle.label | successor | -| Qualifiers.cs:21:9:21:27 | ...; | Qualifiers.cs:21:13:21:26 | access to property StaticProperty | semmle.label | successor | -| Qualifiers.cs:21:13:21:26 | access to property StaticProperty | Qualifiers.cs:21:9:21:26 | ... = ... | semmle.label | successor | -| Qualifiers.cs:22:9:22:26 | ... = ... | Qualifiers.cs:24:9:24:35 | ...; | semmle.label | successor | -| Qualifiers.cs:22:9:22:27 | ...; | Qualifiers.cs:22:13:22:26 | call to method StaticMethod | semmle.label | successor | -| Qualifiers.cs:22:13:22:26 | call to method StaticMethod | Qualifiers.cs:22:9:22:26 | ... = ... | semmle.label | successor | -| Qualifiers.cs:24:9:24:34 | ... = ... | Qualifiers.cs:25:9:25:38 | ...; | semmle.label | successor | -| Qualifiers.cs:24:9:24:35 | ...; | Qualifiers.cs:24:13:24:34 | access to field StaticField | semmle.label | successor | -| Qualifiers.cs:24:13:24:34 | access to field StaticField | Qualifiers.cs:24:9:24:34 | ... = ... | semmle.label | successor | -| Qualifiers.cs:25:9:25:37 | ... = ... | Qualifiers.cs:26:9:26:38 | ...; | semmle.label | successor | -| Qualifiers.cs:25:9:25:38 | ...; | Qualifiers.cs:25:13:25:37 | access to property StaticProperty | semmle.label | successor | -| Qualifiers.cs:25:13:25:37 | access to property StaticProperty | Qualifiers.cs:25:9:25:37 | ... = ... | semmle.label | successor | -| Qualifiers.cs:26:9:26:37 | ... = ... | Qualifiers.cs:28:9:28:41 | ...; | semmle.label | successor | -| Qualifiers.cs:26:9:26:38 | ...; | Qualifiers.cs:26:13:26:37 | call to method StaticMethod | semmle.label | successor | -| Qualifiers.cs:26:13:26:37 | call to method StaticMethod | Qualifiers.cs:26:9:26:37 | ... = ... | semmle.label | successor | -| Qualifiers.cs:28:9:28:40 | ... = ... | Qualifiers.cs:29:9:29:47 | ...; | semmle.label | successor | -| Qualifiers.cs:28:9:28:41 | ...; | Qualifiers.cs:28:13:28:34 | access to field StaticField | semmle.label | successor | -| Qualifiers.cs:28:13:28:34 | access to field StaticField | Qualifiers.cs:28:13:28:40 | access to field Field | semmle.label | successor | -| Qualifiers.cs:28:13:28:40 | access to field Field | Qualifiers.cs:28:9:28:40 | ... = ... | semmle.label | successor | -| Qualifiers.cs:29:9:29:46 | ... = ... | Qualifiers.cs:30:9:30:47 | ...; | semmle.label | successor | -| Qualifiers.cs:29:9:29:47 | ...; | Qualifiers.cs:29:13:29:37 | access to property StaticProperty | semmle.label | successor | -| Qualifiers.cs:29:13:29:37 | access to property StaticProperty | Qualifiers.cs:29:13:29:46 | access to property Property | semmle.label | successor | -| Qualifiers.cs:29:13:29:46 | access to property Property | Qualifiers.cs:29:9:29:46 | ... = ... | semmle.label | successor | -| Qualifiers.cs:30:9:30:46 | ... = ... | Qualifiers.cs:10:10:10:10 | exit M (normal) | semmle.label | successor | -| Qualifiers.cs:30:9:30:47 | ...; | Qualifiers.cs:30:13:30:37 | call to method StaticMethod | semmle.label | successor | -| Qualifiers.cs:30:13:30:37 | call to method StaticMethod | Qualifiers.cs:30:13:30:46 | call to method Method | semmle.label | successor | -| Qualifiers.cs:30:13:30:46 | call to method Method | Qualifiers.cs:30:9:30:46 | ... = ... | semmle.label | successor | -| Switch.cs:5:10:5:11 | enter M1 | Switch.cs:6:5:8:5 | {...} | semmle.label | successor | -| Switch.cs:5:10:5:11 | exit M1 (normal) | Switch.cs:5:10:5:11 | exit M1 | semmle.label | successor | -| Switch.cs:6:5:8:5 | {...} | Switch.cs:7:9:7:22 | switch (...) {...} | semmle.label | successor | -| Switch.cs:7:9:7:22 | switch (...) {...} | Switch.cs:7:17:7:17 | access to parameter o | semmle.label | successor | -| Switch.cs:7:17:7:17 | access to parameter o | Switch.cs:5:10:5:11 | exit M1 (normal) | semmle.label | successor | -| Switch.cs:10:10:10:11 | enter M2 | Switch.cs:11:5:33:5 | {...} | semmle.label | successor | -| Switch.cs:10:10:10:11 | exit M2 (abnormal) | Switch.cs:10:10:10:11 | exit M2 | semmle.label | successor | -| Switch.cs:10:10:10:11 | exit M2 (normal) | Switch.cs:10:10:10:11 | exit M2 | semmle.label | successor | -| Switch.cs:11:5:33:5 | {...} | Switch.cs:12:9:32:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:12:9:32:9 | switch (...) {...} | Switch.cs:12:17:12:17 | access to parameter o | semmle.label | successor | -| Switch.cs:12:17:12:17 | access to parameter o | Switch.cs:14:13:14:21 | case ...: | semmle.label | successor | -| Switch.cs:14:13:14:21 | case ...: | Switch.cs:14:18:14:20 | "a" | semmle.label | successor | -| Switch.cs:14:18:14:20 | "a" | Switch.cs:15:17:15:23 | return ...; | semmle.label | match | -| Switch.cs:14:18:14:20 | "a" | Switch.cs:16:13:16:19 | case ...: | semmle.label | no-match | -| Switch.cs:15:17:15:23 | return ...; | Switch.cs:10:10:10:11 | exit M2 (normal) | semmle.label | return | -| Switch.cs:16:13:16:19 | case ...: | Switch.cs:16:18:16:18 | 0 | semmle.label | successor | -| Switch.cs:16:18:16:18 | 0 | Switch.cs:17:23:17:37 | object creation of type Exception | semmle.label | match | -| Switch.cs:16:18:16:18 | 0 | Switch.cs:18:13:18:22 | case ...: | semmle.label | no-match | -| Switch.cs:17:17:17:38 | throw ...; | Switch.cs:10:10:10:11 | exit M2 (abnormal) | semmle.label | exception(Exception) | -| Switch.cs:17:23:17:37 | object creation of type Exception | Switch.cs:17:17:17:38 | throw ...; | semmle.label | successor | -| Switch.cs:18:13:18:22 | case ...: | Switch.cs:18:18:18:21 | null | semmle.label | successor | -| Switch.cs:18:18:18:21 | null | Switch.cs:19:17:19:29 | goto default; | semmle.label | match | -| Switch.cs:18:18:18:21 | null | Switch.cs:20:13:20:23 | case ...: | semmle.label | no-match | -| Switch.cs:19:17:19:29 | goto default; | Switch.cs:30:13:30:20 | default: | semmle.label | goto(default) | -| Switch.cs:20:13:20:23 | case ...: | Switch.cs:20:18:20:22 | Int32 i | semmle.label | successor | -| Switch.cs:20:18:20:22 | Int32 i | Switch.cs:21:17:22:27 | if (...) ... | semmle.label | match | -| Switch.cs:20:18:20:22 | Int32 i | Switch.cs:24:13:24:56 | case ...: | semmle.label | no-match | -| Switch.cs:21:17:22:27 | if (...) ... | Switch.cs:21:21:21:21 | access to parameter o | semmle.label | successor | -| Switch.cs:21:21:21:21 | access to parameter o | Switch.cs:21:26:21:29 | null | semmle.label | successor | -| Switch.cs:21:21:21:29 | ... == ... | Switch.cs:22:21:22:27 | return ...; | semmle.label | true | -| Switch.cs:21:21:21:29 | ... == ... | Switch.cs:23:27:23:27 | 0 | semmle.label | false | -| Switch.cs:21:26:21:29 | null | Switch.cs:21:21:21:29 | ... == ... | semmle.label | successor | -| Switch.cs:22:21:22:27 | return ...; | Switch.cs:10:10:10:11 | exit M2 (normal) | semmle.label | return | -| Switch.cs:23:17:23:28 | goto case ...; | Switch.cs:16:13:16:19 | case ...: | semmle.label | goto(0) | -| Switch.cs:23:27:23:27 | 0 | Switch.cs:23:17:23:28 | goto case ...; | semmle.label | successor | -| Switch.cs:24:13:24:56 | case ...: | Switch.cs:24:18:24:25 | String s | semmle.label | successor | -| Switch.cs:24:18:24:25 | String s | Switch.cs:24:32:24:32 | access to local variable s | semmle.label | match | -| Switch.cs:24:18:24:25 | String s | Switch.cs:27:13:27:39 | case ...: | semmle.label | no-match | -| Switch.cs:24:32:24:32 | access to local variable s | Switch.cs:24:32:24:39 | access to property Length | semmle.label | successor | -| Switch.cs:24:32:24:39 | access to property Length | Switch.cs:24:43:24:43 | 0 | semmle.label | successor | -| Switch.cs:24:32:24:43 | ... > ... | Switch.cs:24:32:24:55 | [false] ... && ... | semmle.label | false | -| Switch.cs:24:32:24:43 | ... > ... | Switch.cs:24:48:24:48 | access to local variable s | semmle.label | true | -| Switch.cs:24:32:24:55 | [false] ... && ... | Switch.cs:27:13:27:39 | case ...: | semmle.label | false | -| Switch.cs:24:32:24:55 | [true] ... && ... | Switch.cs:25:17:25:37 | ...; | semmle.label | true | -| Switch.cs:24:43:24:43 | 0 | Switch.cs:24:32:24:43 | ... > ... | semmle.label | successor | -| Switch.cs:24:48:24:48 | access to local variable s | Switch.cs:24:53:24:55 | "a" | semmle.label | successor | -| Switch.cs:24:48:24:55 | ... != ... | Switch.cs:24:32:24:55 | [false] ... && ... | semmle.label | false | -| Switch.cs:24:48:24:55 | ... != ... | Switch.cs:24:32:24:55 | [true] ... && ... | semmle.label | true | -| Switch.cs:24:53:24:55 | "a" | Switch.cs:24:48:24:55 | ... != ... | semmle.label | successor | -| Switch.cs:25:17:25:36 | call to method WriteLine | Switch.cs:26:17:26:23 | return ...; | semmle.label | successor | -| Switch.cs:25:17:25:37 | ...; | Switch.cs:25:35:25:35 | access to local variable s | semmle.label | successor | -| Switch.cs:25:35:25:35 | access to local variable s | Switch.cs:25:17:25:36 | call to method WriteLine | semmle.label | successor | -| Switch.cs:26:17:26:23 | return ...; | Switch.cs:10:10:10:11 | exit M2 (normal) | semmle.label | return | -| Switch.cs:27:13:27:39 | case ...: | Switch.cs:27:18:27:25 | Double d | semmle.label | successor | -| Switch.cs:27:18:27:25 | Double d | Switch.cs:27:32:27:38 | call to method Throw | semmle.label | match | -| Switch.cs:27:18:27:25 | Double d | Switch.cs:30:13:30:20 | default: | semmle.label | no-match | -| Switch.cs:27:32:27:38 | call to method Throw | Switch.cs:10:10:10:11 | exit M2 (abnormal) | semmle.label | exception(Exception) | -| Switch.cs:28:13:28:17 | Label: | Switch.cs:29:17:29:23 | return ...; | semmle.label | successor | -| Switch.cs:29:17:29:23 | return ...; | Switch.cs:10:10:10:11 | exit M2 (normal) | semmle.label | return | -| Switch.cs:30:13:30:20 | default: | Switch.cs:31:17:31:27 | goto ...; | semmle.label | successor | -| Switch.cs:31:17:31:27 | goto ...; | Switch.cs:28:13:28:17 | Label: | semmle.label | goto(Label) | -| Switch.cs:35:10:35:11 | enter M3 | Switch.cs:36:5:42:5 | {...} | semmle.label | successor | -| Switch.cs:35:10:35:11 | exit M3 (abnormal) | Switch.cs:35:10:35:11 | exit M3 | semmle.label | successor | -| Switch.cs:36:5:42:5 | {...} | Switch.cs:37:9:41:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:37:9:41:9 | switch (...) {...} | Switch.cs:37:17:37:23 | call to method Throw | semmle.label | successor | -| Switch.cs:37:17:37:23 | call to method Throw | Switch.cs:35:10:35:11 | exit M3 (abnormal) | semmle.label | exception(Exception) | -| Switch.cs:44:10:44:11 | enter M4 | Switch.cs:45:5:53:5 | {...} | semmle.label | successor | -| Switch.cs:44:10:44:11 | exit M4 (normal) | Switch.cs:44:10:44:11 | exit M4 | semmle.label | successor | -| Switch.cs:45:5:53:5 | {...} | Switch.cs:46:9:52:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:46:9:52:9 | switch (...) {...} | Switch.cs:46:17:46:17 | access to parameter o | semmle.label | successor | -| Switch.cs:46:17:46:17 | access to parameter o | Switch.cs:48:13:48:23 | case ...: | semmle.label | successor | -| Switch.cs:48:13:48:23 | case ...: | Switch.cs:48:18:48:20 | access to type Int32 | semmle.label | successor | -| Switch.cs:48:18:48:20 | access to type Int32 | Switch.cs:49:17:49:22 | break; | semmle.label | match | -| Switch.cs:48:18:48:20 | access to type Int32 | Switch.cs:50:13:50:39 | case ...: | semmle.label | no-match | -| Switch.cs:49:17:49:22 | break; | Switch.cs:44:10:44:11 | exit M4 (normal) | semmle.label | break | -| Switch.cs:50:13:50:39 | case ...: | Switch.cs:50:18:50:21 | access to type Boolean | semmle.label | successor | -| Switch.cs:50:18:50:21 | access to type Boolean | Switch.cs:44:10:44:11 | exit M4 (normal) | semmle.label | no-match | -| Switch.cs:50:18:50:21 | access to type Boolean | Switch.cs:50:30:50:30 | access to parameter o | semmle.label | match | -| Switch.cs:50:30:50:30 | access to parameter o | Switch.cs:50:35:50:38 | null | semmle.label | successor | -| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:44:10:44:11 | exit M4 (normal) | semmle.label | false | -| Switch.cs:50:30:50:38 | ... != ... | Switch.cs:51:17:51:22 | break; | semmle.label | true | -| Switch.cs:50:35:50:38 | null | Switch.cs:50:30:50:38 | ... != ... | semmle.label | successor | -| Switch.cs:51:17:51:22 | break; | Switch.cs:44:10:44:11 | exit M4 (normal) | semmle.label | break | -| Switch.cs:55:10:55:11 | enter M5 | Switch.cs:56:5:64:5 | {...} | semmle.label | successor | -| Switch.cs:55:10:55:11 | exit M5 (normal) | Switch.cs:55:10:55:11 | exit M5 | semmle.label | successor | -| Switch.cs:56:5:64:5 | {...} | Switch.cs:57:9:63:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:57:9:63:9 | switch (...) {...} | Switch.cs:57:17:57:17 | 1 | semmle.label | successor | -| Switch.cs:57:17:57:17 | 1 | Switch.cs:57:21:57:21 | 2 | semmle.label | successor | -| Switch.cs:57:17:57:21 | ... + ... | Switch.cs:59:13:59:19 | case ...: | semmle.label | successor | -| Switch.cs:57:21:57:21 | 2 | Switch.cs:57:17:57:21 | ... + ... | semmle.label | successor | -| Switch.cs:59:13:59:19 | case ...: | Switch.cs:59:18:59:18 | 2 | semmle.label | successor | -| Switch.cs:59:18:59:18 | 2 | Switch.cs:61:13:61:19 | case ...: | semmle.label | no-match | -| Switch.cs:61:13:61:19 | case ...: | Switch.cs:61:18:61:18 | 3 | semmle.label | successor | -| Switch.cs:61:18:61:18 | 3 | Switch.cs:62:17:62:22 | break; | semmle.label | match | -| Switch.cs:62:17:62:22 | break; | Switch.cs:55:10:55:11 | exit M5 (normal) | semmle.label | break | -| Switch.cs:66:10:66:11 | enter M6 | Switch.cs:67:5:75:5 | {...} | semmle.label | successor | -| Switch.cs:66:10:66:11 | exit M6 (normal) | Switch.cs:66:10:66:11 | exit M6 | semmle.label | successor | -| Switch.cs:67:5:75:5 | {...} | Switch.cs:68:9:74:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:68:9:74:9 | switch (...) {...} | Switch.cs:68:25:68:25 | access to parameter s | semmle.label | successor | -| Switch.cs:68:17:68:25 | (...) ... | Switch.cs:70:13:70:23 | case ...: | semmle.label | successor | -| Switch.cs:68:25:68:25 | access to parameter s | Switch.cs:68:17:68:25 | (...) ... | semmle.label | successor | -| Switch.cs:70:13:70:23 | case ...: | Switch.cs:70:18:70:20 | access to type Int32 | semmle.label | successor | -| Switch.cs:70:18:70:20 | access to type Int32 | Switch.cs:72:13:72:20 | case ...: | semmle.label | no-match | -| Switch.cs:72:13:72:20 | case ...: | Switch.cs:72:18:72:19 | "" | semmle.label | successor | -| Switch.cs:72:18:72:19 | "" | Switch.cs:66:10:66:11 | exit M6 (normal) | semmle.label | no-match | -| Switch.cs:72:18:72:19 | "" | Switch.cs:73:17:73:22 | break; | semmle.label | match | -| Switch.cs:73:17:73:22 | break; | Switch.cs:66:10:66:11 | exit M6 (normal) | semmle.label | break | -| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:78:5:89:5 | {...} | semmle.label | successor | -| Switch.cs:77:10:77:11 | exit M7 (normal) | Switch.cs:77:10:77:11 | exit M7 | semmle.label | successor | -| Switch.cs:78:5:89:5 | {...} | Switch.cs:79:9:87:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:79:9:87:9 | switch (...) {...} | Switch.cs:79:17:79:17 | access to parameter i | semmle.label | successor | -| Switch.cs:79:17:79:17 | access to parameter i | Switch.cs:81:13:81:19 | case ...: | semmle.label | successor | -| Switch.cs:81:13:81:19 | case ...: | Switch.cs:81:18:81:18 | 1 | semmle.label | successor | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:82:24:82:27 | true | semmle.label | match | -| Switch.cs:81:18:81:18 | 1 | Switch.cs:83:13:83:19 | case ...: | semmle.label | no-match | -| Switch.cs:82:17:82:28 | return ...; | Switch.cs:77:10:77:11 | exit M7 (normal) | semmle.label | return | -| Switch.cs:82:24:82:27 | true | Switch.cs:82:17:82:28 | return ...; | semmle.label | successor | -| Switch.cs:83:13:83:19 | case ...: | Switch.cs:83:18:83:18 | 2 | semmle.label | successor | -| Switch.cs:83:18:83:18 | 2 | Switch.cs:84:17:85:26 | if (...) ... | semmle.label | match | -| Switch.cs:83:18:83:18 | 2 | Switch.cs:88:16:88:20 | false | semmle.label | no-match | -| Switch.cs:84:17:85:26 | if (...) ... | Switch.cs:84:21:84:21 | access to parameter j | semmle.label | successor | -| Switch.cs:84:21:84:21 | access to parameter j | Switch.cs:84:25:84:25 | 2 | semmle.label | successor | -| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:85:21:85:26 | break; | semmle.label | true | -| Switch.cs:84:21:84:25 | ... > ... | Switch.cs:86:24:86:27 | true | semmle.label | false | -| Switch.cs:84:25:84:25 | 2 | Switch.cs:84:21:84:25 | ... > ... | semmle.label | successor | -| Switch.cs:85:21:85:26 | break; | Switch.cs:88:16:88:20 | false | semmle.label | break | -| Switch.cs:86:17:86:28 | return ...; | Switch.cs:77:10:77:11 | exit M7 (normal) | semmle.label | return | -| Switch.cs:86:24:86:27 | true | Switch.cs:86:17:86:28 | return ...; | semmle.label | successor | -| Switch.cs:88:9:88:21 | return ...; | Switch.cs:77:10:77:11 | exit M7 (normal) | semmle.label | return | -| Switch.cs:88:16:88:20 | false | Switch.cs:88:9:88:21 | return ...; | semmle.label | successor | -| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:92:5:99:5 | {...} | semmle.label | successor | -| Switch.cs:91:10:91:11 | exit M8 (normal) | Switch.cs:91:10:91:11 | exit M8 | semmle.label | successor | -| Switch.cs:92:5:99:5 | {...} | Switch.cs:93:9:97:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:93:9:97:9 | switch (...) {...} | Switch.cs:93:17:93:17 | access to parameter o | semmle.label | successor | -| Switch.cs:93:17:93:17 | access to parameter o | Switch.cs:95:13:95:23 | case ...: | semmle.label | successor | -| Switch.cs:95:13:95:23 | case ...: | Switch.cs:95:18:95:20 | access to type Int32 | semmle.label | successor | -| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:96:24:96:27 | true | semmle.label | match | -| Switch.cs:95:18:95:20 | access to type Int32 | Switch.cs:98:16:98:20 | false | semmle.label | no-match | -| Switch.cs:96:17:96:28 | return ...; | Switch.cs:91:10:91:11 | exit M8 (normal) | semmle.label | return | -| Switch.cs:96:24:96:27 | true | Switch.cs:96:17:96:28 | return ...; | semmle.label | successor | -| Switch.cs:98:9:98:21 | return ...; | Switch.cs:91:10:91:11 | exit M8 (normal) | semmle.label | return | -| Switch.cs:98:16:98:20 | false | Switch.cs:98:9:98:21 | return ...; | semmle.label | successor | -| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:102:5:109:5 | {...} | semmle.label | successor | -| Switch.cs:101:9:101:10 | exit M9 (normal) | Switch.cs:101:9:101:10 | exit M9 | semmle.label | successor | -| Switch.cs:102:5:109:5 | {...} | Switch.cs:103:9:107:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:103:9:107:9 | switch (...) {...} | Switch.cs:103:17:103:17 | access to parameter s | semmle.label | successor | -| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:103:19:103:25 | access to property Length | semmle.label | non-null | -| Switch.cs:103:17:103:17 | access to parameter s | Switch.cs:105:13:105:19 | case ...: | semmle.label | null | -| Switch.cs:103:19:103:25 | access to property Length | Switch.cs:105:13:105:19 | case ...: | semmle.label | successor | -| Switch.cs:105:13:105:19 | case ...: | Switch.cs:105:18:105:18 | 0 | semmle.label | successor | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:105:28:105:28 | 0 | semmle.label | match | -| Switch.cs:105:18:105:18 | 0 | Switch.cs:106:13:106:19 | case ...: | semmle.label | no-match | -| Switch.cs:105:21:105:29 | return ...; | Switch.cs:101:9:101:10 | exit M9 (normal) | semmle.label | return | -| Switch.cs:105:28:105:28 | 0 | Switch.cs:105:21:105:29 | return ...; | semmle.label | successor | -| Switch.cs:106:13:106:19 | case ...: | Switch.cs:106:18:106:18 | 1 | semmle.label | successor | -| Switch.cs:106:18:106:18 | 1 | Switch.cs:106:28:106:28 | 1 | semmle.label | match | -| Switch.cs:106:18:106:18 | 1 | Switch.cs:108:17:108:17 | 1 | semmle.label | no-match | -| Switch.cs:106:21:106:29 | return ...; | Switch.cs:101:9:101:10 | exit M9 (normal) | semmle.label | return | -| Switch.cs:106:28:106:28 | 1 | Switch.cs:106:21:106:29 | return ...; | semmle.label | successor | -| Switch.cs:108:9:108:18 | return ...; | Switch.cs:101:9:101:10 | exit M9 (normal) | semmle.label | return | -| Switch.cs:108:16:108:17 | -... | Switch.cs:108:9:108:18 | return ...; | semmle.label | successor | -| Switch.cs:108:17:108:17 | 1 | Switch.cs:108:16:108:17 | -... | semmle.label | successor | -| Switch.cs:111:17:111:21 | enter Throw | Switch.cs:111:34:111:48 | object creation of type Exception | semmle.label | successor | -| Switch.cs:111:17:111:21 | exit Throw (abnormal) | Switch.cs:111:17:111:21 | exit Throw | semmle.label | successor | -| Switch.cs:111:28:111:48 | throw ... | Switch.cs:111:17:111:21 | exit Throw (abnormal) | semmle.label | exception(Exception) | -| Switch.cs:111:34:111:48 | object creation of type Exception | Switch.cs:111:28:111:48 | throw ... | semmle.label | successor | -| Switch.cs:113:9:113:11 | enter M10 | Switch.cs:114:5:121:5 | {...} | semmle.label | successor | -| Switch.cs:113:9:113:11 | exit M10 (normal) | Switch.cs:113:9:113:11 | exit M10 | semmle.label | successor | -| Switch.cs:114:5:121:5 | {...} | Switch.cs:115:9:119:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:115:9:119:9 | switch (...) {...} | Switch.cs:115:17:115:17 | access to parameter s | semmle.label | successor | -| Switch.cs:115:17:115:17 | access to parameter s | Switch.cs:115:17:115:24 | access to property Length | semmle.label | successor | -| Switch.cs:115:17:115:24 | access to property Length | Switch.cs:117:13:117:35 | case ...: | semmle.label | successor | -| Switch.cs:117:13:117:35 | case ...: | Switch.cs:117:18:117:18 | 3 | semmle.label | successor | -| Switch.cs:117:18:117:18 | 3 | Switch.cs:117:25:117:25 | access to parameter s | semmle.label | match | -| Switch.cs:117:18:117:18 | 3 | Switch.cs:118:13:118:34 | case ...: | semmle.label | no-match | -| Switch.cs:117:25:117:25 | access to parameter s | Switch.cs:117:30:117:34 | "foo" | semmle.label | successor | -| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:117:44:117:44 | 1 | semmle.label | true | -| Switch.cs:117:25:117:34 | ... == ... | Switch.cs:118:13:118:34 | case ...: | semmle.label | false | -| Switch.cs:117:30:117:34 | "foo" | Switch.cs:117:25:117:34 | ... == ... | semmle.label | successor | -| Switch.cs:117:37:117:45 | return ...; | Switch.cs:113:9:113:11 | exit M10 (normal) | semmle.label | return | -| Switch.cs:117:44:117:44 | 1 | Switch.cs:117:37:117:45 | return ...; | semmle.label | successor | -| Switch.cs:118:13:118:34 | case ...: | Switch.cs:118:18:118:18 | 2 | semmle.label | successor | -| Switch.cs:118:18:118:18 | 2 | Switch.cs:118:25:118:25 | access to parameter s | semmle.label | match | -| Switch.cs:118:18:118:18 | 2 | Switch.cs:120:17:120:17 | 1 | semmle.label | no-match | -| Switch.cs:118:25:118:25 | access to parameter s | Switch.cs:118:30:118:33 | "fu" | semmle.label | successor | -| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:118:43:118:43 | 2 | semmle.label | true | -| Switch.cs:118:25:118:33 | ... == ... | Switch.cs:120:17:120:17 | 1 | semmle.label | false | -| Switch.cs:118:30:118:33 | "fu" | Switch.cs:118:25:118:33 | ... == ... | semmle.label | successor | -| Switch.cs:118:36:118:44 | return ...; | Switch.cs:113:9:113:11 | exit M10 (normal) | semmle.label | return | -| Switch.cs:118:43:118:43 | 2 | Switch.cs:118:36:118:44 | return ...; | semmle.label | successor | -| Switch.cs:120:9:120:18 | return ...; | Switch.cs:113:9:113:11 | exit M10 (normal) | semmle.label | return | -| Switch.cs:120:16:120:17 | -... | Switch.cs:120:9:120:18 | return ...; | semmle.label | successor | -| Switch.cs:120:17:120:17 | 1 | Switch.cs:120:16:120:17 | -... | semmle.label | successor | -| Switch.cs:123:10:123:12 | enter M11 | Switch.cs:124:5:127:5 | {...} | semmle.label | successor | -| Switch.cs:123:10:123:12 | exit M11 (normal) | Switch.cs:123:10:123:12 | exit M11 | semmle.label | successor | -| Switch.cs:124:5:127:5 | {...} | Switch.cs:125:9:126:19 | if (...) ... | semmle.label | successor | -| Switch.cs:125:9:126:19 | if (...) ... | Switch.cs:125:13:125:13 | access to parameter o | semmle.label | successor | -| Switch.cs:125:13:125:13 | access to parameter o | Switch.cs:125:24:125:29 | Boolean b | semmle.label | successor | -| Switch.cs:125:13:125:48 | [false] ... switch { ... } | Switch.cs:123:10:123:12 | exit M11 (normal) | semmle.label | false | -| Switch.cs:125:13:125:48 | [true] ... switch { ... } | Switch.cs:126:13:126:19 | return ...; | semmle.label | true | -| Switch.cs:125:24:125:29 | Boolean b | Switch.cs:125:34:125:34 | access to local variable b | semmle.label | match | -| Switch.cs:125:24:125:29 | Boolean b | Switch.cs:125:37:125:37 | _ | semmle.label | no-match | -| Switch.cs:125:24:125:34 | [false] ... => ... | Switch.cs:125:13:125:48 | [false] ... switch { ... } | semmle.label | false | -| Switch.cs:125:24:125:34 | [true] ... => ... | Switch.cs:125:13:125:48 | [true] ... switch { ... } | semmle.label | true | -| Switch.cs:125:34:125:34 | access to local variable b | Switch.cs:125:24:125:34 | [false] ... => ... | semmle.label | false | -| Switch.cs:125:34:125:34 | access to local variable b | Switch.cs:125:24:125:34 | [true] ... => ... | semmle.label | true | -| Switch.cs:125:37:125:37 | _ | Switch.cs:125:42:125:46 | false | semmle.label | match | -| Switch.cs:125:37:125:46 | [false] ... => ... | Switch.cs:125:13:125:48 | [false] ... switch { ... } | semmle.label | false | -| Switch.cs:125:42:125:46 | false | Switch.cs:125:37:125:46 | [false] ... => ... | semmle.label | false | -| Switch.cs:126:13:126:19 | return ...; | Switch.cs:123:10:123:12 | exit M11 (normal) | semmle.label | return | -| Switch.cs:129:12:129:14 | enter M12 | Switch.cs:130:5:132:5 | {...} | semmle.label | successor | -| Switch.cs:129:12:129:14 | exit M12 (normal) | Switch.cs:129:12:129:14 | exit M12 | semmle.label | successor | -| Switch.cs:130:5:132:5 | {...} | Switch.cs:131:17:131:17 | access to parameter o | semmle.label | successor | -| Switch.cs:131:9:131:67 | return ...; | Switch.cs:129:12:129:14 | exit M12 (normal) | semmle.label | return | -| Switch.cs:131:17:131:17 | access to parameter o | Switch.cs:131:28:131:35 | String s | semmle.label | successor | -| Switch.cs:131:17:131:53 | [non-null] ... switch { ... } | Switch.cs:131:56:131:66 | call to method ToString | semmle.label | non-null | -| Switch.cs:131:17:131:53 | [null] ... switch { ... } | Switch.cs:131:9:131:67 | return ...; | semmle.label | null | -| Switch.cs:131:28:131:35 | String s | Switch.cs:131:40:131:40 | access to local variable s | semmle.label | match | -| Switch.cs:131:28:131:35 | String s | Switch.cs:131:43:131:43 | _ | semmle.label | no-match | -| Switch.cs:131:28:131:40 | [non-null] ... => ... | Switch.cs:131:17:131:53 | [non-null] ... switch { ... } | semmle.label | non-null | -| Switch.cs:131:28:131:40 | [null] ... => ... | Switch.cs:131:17:131:53 | [null] ... switch { ... } | semmle.label | null | -| Switch.cs:131:40:131:40 | access to local variable s | Switch.cs:131:28:131:40 | [non-null] ... => ... | semmle.label | non-null | -| Switch.cs:131:40:131:40 | access to local variable s | Switch.cs:131:28:131:40 | [null] ... => ... | semmle.label | null | -| Switch.cs:131:43:131:43 | _ | Switch.cs:131:48:131:51 | null | semmle.label | match | -| Switch.cs:131:43:131:51 | [null] ... => ... | Switch.cs:131:17:131:53 | [null] ... switch { ... } | semmle.label | null | -| Switch.cs:131:48:131:51 | null | Switch.cs:131:43:131:51 | [null] ... => ... | semmle.label | null | -| Switch.cs:131:56:131:66 | call to method ToString | Switch.cs:131:9:131:67 | return ...; | semmle.label | successor | -| Switch.cs:134:9:134:11 | enter M13 | Switch.cs:135:5:142:5 | {...} | semmle.label | successor | -| Switch.cs:134:9:134:11 | exit M13 (normal) | Switch.cs:134:9:134:11 | exit M13 | semmle.label | successor | -| Switch.cs:135:5:142:5 | {...} | Switch.cs:136:9:141:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:136:9:141:9 | switch (...) {...} | Switch.cs:136:17:136:17 | access to parameter i | semmle.label | successor | -| Switch.cs:136:17:136:17 | access to parameter i | Switch.cs:139:13:139:19 | case ...: | semmle.label | successor | -| Switch.cs:138:13:138:20 | default: | Switch.cs:138:30:138:30 | 1 | semmle.label | successor | -| Switch.cs:138:22:138:31 | return ...; | Switch.cs:134:9:134:11 | exit M13 (normal) | semmle.label | return | -| Switch.cs:138:29:138:30 | -... | Switch.cs:138:22:138:31 | return ...; | semmle.label | successor | -| Switch.cs:138:30:138:30 | 1 | Switch.cs:138:29:138:30 | -... | semmle.label | successor | -| Switch.cs:139:13:139:19 | case ...: | Switch.cs:139:18:139:18 | 1 | semmle.label | successor | -| Switch.cs:139:18:139:18 | 1 | Switch.cs:139:28:139:28 | 1 | semmle.label | match | -| Switch.cs:139:18:139:18 | 1 | Switch.cs:140:13:140:19 | case ...: | semmle.label | no-match | -| Switch.cs:139:21:139:29 | return ...; | Switch.cs:134:9:134:11 | exit M13 (normal) | semmle.label | return | -| Switch.cs:139:28:139:28 | 1 | Switch.cs:139:21:139:29 | return ...; | semmle.label | successor | -| Switch.cs:140:13:140:19 | case ...: | Switch.cs:140:18:140:18 | 2 | semmle.label | successor | -| Switch.cs:140:18:140:18 | 2 | Switch.cs:138:13:138:20 | default: | semmle.label | no-match | -| Switch.cs:140:18:140:18 | 2 | Switch.cs:140:28:140:28 | 2 | semmle.label | match | -| Switch.cs:140:21:140:29 | return ...; | Switch.cs:134:9:134:11 | exit M13 (normal) | semmle.label | return | -| Switch.cs:140:28:140:28 | 2 | Switch.cs:140:21:140:29 | return ...; | semmle.label | successor | -| Switch.cs:144:9:144:11 | enter M14 | Switch.cs:145:5:152:5 | {...} | semmle.label | successor | -| Switch.cs:144:9:144:11 | exit M14 (normal) | Switch.cs:144:9:144:11 | exit M14 | semmle.label | successor | -| Switch.cs:145:5:152:5 | {...} | Switch.cs:146:9:151:9 | switch (...) {...} | semmle.label | successor | -| Switch.cs:146:9:151:9 | switch (...) {...} | Switch.cs:146:17:146:17 | access to parameter i | semmle.label | successor | -| Switch.cs:146:17:146:17 | access to parameter i | Switch.cs:148:13:148:19 | case ...: | semmle.label | successor | -| Switch.cs:148:13:148:19 | case ...: | Switch.cs:148:18:148:18 | 1 | semmle.label | successor | -| Switch.cs:148:18:148:18 | 1 | Switch.cs:148:28:148:28 | 1 | semmle.label | match | -| Switch.cs:148:18:148:18 | 1 | Switch.cs:150:13:150:19 | case ...: | semmle.label | no-match | -| Switch.cs:148:21:148:29 | return ...; | Switch.cs:144:9:144:11 | exit M14 (normal) | semmle.label | return | -| Switch.cs:148:28:148:28 | 1 | Switch.cs:148:21:148:29 | return ...; | semmle.label | successor | -| Switch.cs:149:13:149:20 | default: | Switch.cs:149:30:149:30 | 1 | semmle.label | successor | -| Switch.cs:149:22:149:31 | return ...; | Switch.cs:144:9:144:11 | exit M14 (normal) | semmle.label | return | -| Switch.cs:149:29:149:30 | -... | Switch.cs:149:22:149:31 | return ...; | semmle.label | successor | -| Switch.cs:149:30:149:30 | 1 | Switch.cs:149:29:149:30 | -... | semmle.label | successor | -| Switch.cs:150:13:150:19 | case ...: | Switch.cs:150:18:150:18 | 2 | semmle.label | successor | -| Switch.cs:150:18:150:18 | 2 | Switch.cs:149:13:149:20 | default: | semmle.label | no-match | -| Switch.cs:150:18:150:18 | 2 | Switch.cs:150:28:150:28 | 2 | semmle.label | match | -| Switch.cs:150:21:150:29 | return ...; | Switch.cs:144:9:144:11 | exit M14 (normal) | semmle.label | return | -| Switch.cs:150:28:150:28 | 2 | Switch.cs:150:21:150:29 | return ...; | semmle.label | successor | -| Switch.cs:154:10:154:12 | enter M15 | Switch.cs:155:5:161:5 | {...} | semmle.label | successor | -| Switch.cs:154:10:154:12 | exit M15 (abnormal) | Switch.cs:154:10:154:12 | exit M15 | semmle.label | successor | -| Switch.cs:154:10:154:12 | exit M15 (normal) | Switch.cs:154:10:154:12 | exit M15 | semmle.label | successor | -| Switch.cs:155:5:161:5 | {...} | Switch.cs:156:9:156:55 | ... ...; | semmle.label | successor | -| Switch.cs:156:9:156:55 | ... ...; | Switch.cs:156:17:156:17 | access to parameter b | semmle.label | successor | -| Switch.cs:156:13:156:54 | String s = ... | Switch.cs:157:9:160:49 | if (...) ... | semmle.label | successor | -| Switch.cs:156:17:156:17 | access to parameter b | Switch.cs:156:28:156:31 | true | semmle.label | successor | -| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:156:13:156:54 | String s = ... | semmle.label | successor | -| Switch.cs:156:28:156:31 | true | Switch.cs:156:36:156:38 | "a" | semmle.label | match | -| Switch.cs:156:28:156:31 | true | Switch.cs:156:41:156:45 | false | semmle.label | no-match | -| Switch.cs:156:28:156:38 | ... => ... | Switch.cs:156:17:156:54 | ... switch { ... } | semmle.label | successor | -| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:28:156:38 | ... => ... | semmle.label | successor | -| Switch.cs:156:41:156:45 | false | Switch.cs:154:10:154:12 | exit M15 (abnormal) | semmle.label | exception(InvalidOperationException) | -| Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | semmle.label | match | -| Switch.cs:156:41:156:52 | ... => ... | Switch.cs:156:17:156:54 | ... switch { ... } | semmle.label | successor | -| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:41:156:52 | ... => ... | semmle.label | successor | -| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:157:13:157:13 | access to parameter b | semmle.label | successor | -| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:158:13:158:49 | ...; | semmle.label | true | -| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:160:13:160:49 | ...; | semmle.label | false | -| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:154:10:154:12 | exit M15 (normal) | semmle.label | successor | -| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:40:158:43 | "a = " | semmle.label | successor | -| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:13:158:48 | call to method WriteLine | semmle.label | successor | -| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:45:158:45 | access to local variable s | semmle.label | successor | -| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:38:158:47 | $"..." | semmle.label | successor | -| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:154:10:154:12 | exit M15 (normal) | semmle.label | successor | -| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:40:160:43 | "b = " | semmle.label | successor | -| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:13:160:48 | call to method WriteLine | semmle.label | successor | -| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:45:160:45 | access to local variable s | semmle.label | successor | -| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:38:160:47 | $"..." | semmle.label | successor | -| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:4:5:9:5 | {...} | semmle.label | successor | -| TypeAccesses.cs:3:10:3:10 | exit M (normal) | TypeAccesses.cs:3:10:3:10 | exit M | semmle.label | successor | -| TypeAccesses.cs:4:5:9:5 | {...} | TypeAccesses.cs:5:9:5:26 | ... ...; | semmle.label | successor | -| TypeAccesses.cs:5:9:5:26 | ... ...; | TypeAccesses.cs:5:25:5:25 | access to parameter o | semmle.label | successor | -| TypeAccesses.cs:5:13:5:25 | String s = ... | TypeAccesses.cs:6:9:6:24 | ...; | semmle.label | successor | -| TypeAccesses.cs:5:17:5:25 | (...) ... | TypeAccesses.cs:5:13:5:25 | String s = ... | semmle.label | successor | -| TypeAccesses.cs:5:25:5:25 | access to parameter o | TypeAccesses.cs:5:17:5:25 | (...) ... | semmle.label | successor | -| TypeAccesses.cs:6:9:6:23 | ... = ... | TypeAccesses.cs:7:9:7:25 | if (...) ... | semmle.label | successor | -| TypeAccesses.cs:6:9:6:24 | ...; | TypeAccesses.cs:6:13:6:13 | access to parameter o | semmle.label | successor | -| TypeAccesses.cs:6:13:6:13 | access to parameter o | TypeAccesses.cs:6:13:6:23 | ... as ... | semmle.label | successor | -| 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 | [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 | -| TypeAccesses.cs:8:17:8:27 | typeof(...) | TypeAccesses.cs:8:13:8:27 | Type t = ... | semmle.label | successor | -| VarDecls.cs:5:18:5:19 | enter M1 | VarDecls.cs:6:5:11:5 | {...} | semmle.label | successor | -| VarDecls.cs:5:18:5:19 | exit M1 (normal) | VarDecls.cs:5:18:5:19 | exit M1 | semmle.label | successor | -| VarDecls.cs:6:5:11:5 | {...} | VarDecls.cs:7:9:10:9 | fixed(...) { ... } | semmle.label | successor | -| VarDecls.cs:7:9:10:9 | fixed(...) { ... } | VarDecls.cs:7:27:7:33 | access to parameter strings | semmle.label | successor | -| VarDecls.cs:7:22:7:36 | Char* c1 = ... | VarDecls.cs:7:44:7:50 | access to parameter strings | semmle.label | successor | -| VarDecls.cs:7:27:7:33 | access to parameter strings | VarDecls.cs:7:35:7:35 | 0 | semmle.label | successor | -| VarDecls.cs:7:27:7:36 | (...) ... | VarDecls.cs:7:22:7:36 | Char* c1 = ... | semmle.label | successor | -| VarDecls.cs:7:27:7:36 | access to array element | VarDecls.cs:7:27:7:36 | (...) ... | semmle.label | successor | -| VarDecls.cs:7:35:7:35 | 0 | VarDecls.cs:7:27:7:36 | access to array element | semmle.label | successor | -| VarDecls.cs:7:39:7:53 | Char* c2 = ... | VarDecls.cs:8:9:10:9 | {...} | semmle.label | successor | -| VarDecls.cs:7:44:7:50 | access to parameter strings | VarDecls.cs:7:52:7:52 | 1 | semmle.label | successor | -| VarDecls.cs:7:44:7:53 | (...) ... | VarDecls.cs:7:39:7:53 | Char* c2 = ... | semmle.label | successor | -| VarDecls.cs:7:44:7:53 | access to array element | VarDecls.cs:7:44:7:53 | (...) ... | semmle.label | successor | -| VarDecls.cs:7:52:7:52 | 1 | VarDecls.cs:7:44:7:53 | access to array element | semmle.label | successor | -| VarDecls.cs:8:9:10:9 | {...} | VarDecls.cs:9:27:9:28 | access to local variable c1 | semmle.label | successor | -| VarDecls.cs:9:13:9:29 | return ...; | VarDecls.cs:5:18:5:19 | exit M1 (normal) | semmle.label | return | -| VarDecls.cs:9:20:9:28 | (...) ... | VarDecls.cs:9:13:9:29 | return ...; | semmle.label | successor | -| VarDecls.cs:9:27:9:28 | access to local variable c1 | VarDecls.cs:9:20:9:28 | (...) ... | semmle.label | successor | -| VarDecls.cs:13:12:13:13 | enter M2 | VarDecls.cs:14:5:17:5 | {...} | semmle.label | successor | -| VarDecls.cs:13:12:13:13 | exit M2 (normal) | VarDecls.cs:13:12:13:13 | exit M2 | semmle.label | successor | -| VarDecls.cs:14:5:17:5 | {...} | VarDecls.cs:15:9:15:30 | ... ...; | semmle.label | successor | -| VarDecls.cs:15:9:15:30 | ... ...; | VarDecls.cs:15:21:15:21 | access to parameter s | semmle.label | successor | -| VarDecls.cs:15:16:15:21 | String s1 = ... | VarDecls.cs:15:29:15:29 | access to parameter s | semmle.label | successor | -| VarDecls.cs:15:21:15:21 | access to parameter s | VarDecls.cs:15:16:15:21 | String s1 = ... | semmle.label | successor | -| VarDecls.cs:15:24:15:29 | String s2 = ... | VarDecls.cs:16:16:16:17 | access to local variable s1 | semmle.label | successor | -| VarDecls.cs:15:29:15:29 | access to parameter s | VarDecls.cs:15:24:15:29 | String s2 = ... | semmle.label | successor | -| VarDecls.cs:16:9:16:23 | return ...; | VarDecls.cs:13:12:13:13 | exit M2 (normal) | semmle.label | return | -| VarDecls.cs:16:16:16:17 | access to local variable s1 | VarDecls.cs:16:21:16:22 | access to local variable s2 | semmle.label | successor | -| VarDecls.cs:16:16:16:22 | ... + ... | VarDecls.cs:16:9:16:23 | return ...; | semmle.label | successor | -| VarDecls.cs:16:21:16:22 | access to local variable s2 | VarDecls.cs:16:16:16:22 | ... + ... | semmle.label | successor | -| VarDecls.cs:19:7:19:8 | enter M3 | VarDecls.cs:20:5:26:5 | {...} | semmle.label | successor | -| VarDecls.cs:19:7:19:8 | exit M3 (normal) | VarDecls.cs:19:7:19:8 | exit M3 | semmle.label | successor | -| VarDecls.cs:20:5:26:5 | {...} | VarDecls.cs:21:9:22:13 | using (...) {...} | semmle.label | successor | -| VarDecls.cs:21:9:22:13 | using (...) {...} | VarDecls.cs:21:16:21:22 | object creation of type C | semmle.label | successor | -| VarDecls.cs:21:16:21:22 | object creation of type C | VarDecls.cs:22:13:22:13 | ; | semmle.label | successor | -| VarDecls.cs:22:13:22:13 | ; | VarDecls.cs:24:9:25:29 | using (...) {...} | semmle.label | successor | -| VarDecls.cs:24:9:25:29 | using (...) {...} | VarDecls.cs:24:22:24:28 | object creation of type C | semmle.label | successor | -| VarDecls.cs:24:18:24:28 | C x = ... | VarDecls.cs:24:35:24:41 | object creation of type C | semmle.label | successor | -| VarDecls.cs:24:22:24:28 | object creation of type C | VarDecls.cs:24:18:24:28 | C x = ... | semmle.label | successor | -| VarDecls.cs:24:31:24:41 | C y = ... | VarDecls.cs:25:20:25:20 | access to parameter b | semmle.label | successor | -| VarDecls.cs:24:35:24:41 | object creation of type C | VarDecls.cs:24:31:24:41 | C y = ... | semmle.label | successor | -| VarDecls.cs:25:13:25:29 | return ...; | VarDecls.cs:19:7:19:8 | exit M3 (normal) | semmle.label | return | -| VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:24:25:24 | access to local variable x | semmle.label | true | -| VarDecls.cs:25:20:25:20 | access to parameter b | VarDecls.cs:25:28:25:28 | access to local variable y | semmle.label | false | -| VarDecls.cs:25:20:25:28 | ... ? ... : ... | VarDecls.cs:25:13:25:29 | return ...; | semmle.label | successor | -| VarDecls.cs:25:24:25:24 | access to local variable x | VarDecls.cs:25:20:25:28 | ... ? ... : ... | semmle.label | successor | -| VarDecls.cs:25:28:25:28 | access to local variable y | VarDecls.cs:25:20:25:28 | ... ? ... : ... | semmle.label | successor | -| VarDecls.cs:28:41:28:47 | enter Dispose | VarDecls.cs:28:51:28:53 | {...} | semmle.label | successor | -| VarDecls.cs:28:41:28:47 | exit Dispose (normal) | VarDecls.cs:28:41:28:47 | exit Dispose | semmle.label | successor | -| VarDecls.cs:28:51:28:53 | {...} | VarDecls.cs:28:41:28:47 | exit Dispose (normal) | semmle.label | successor | -| cflow.cs:5:17:5:20 | enter Main | cflow.cs:6:5:35:5 | {...} | semmle.label | successor | -| cflow.cs:5:17:5:20 | exit Main (normal) | cflow.cs:5:17:5:20 | exit Main | semmle.label | successor | -| cflow.cs:6:5:35:5 | {...} | cflow.cs:7:9:7:28 | ... ...; | semmle.label | successor | -| cflow.cs:7:9:7:28 | ... ...; | cflow.cs:7:17:7:20 | access to parameter args | semmle.label | successor | -| cflow.cs:7:13:7:27 | Int32 a = ... | cflow.cs:9:9:9:40 | ...; | semmle.label | successor | -| cflow.cs:7:17:7:20 | access to parameter args | cflow.cs:7:17:7:27 | access to property Length | semmle.label | successor | -| cflow.cs:7:17:7:27 | access to property Length | cflow.cs:7:13:7:27 | Int32 a = ... | semmle.label | successor | -| cflow.cs:9:9:9:39 | ... = ... | cflow.cs:11:9:12:49 | if (...) ... | semmle.label | successor | -| cflow.cs:9:9:9:40 | ...; | cflow.cs:9:13:9:29 | object creation of type ControlFlow | semmle.label | successor | -| cflow.cs:9:13:9:29 | object creation of type ControlFlow | cflow.cs:9:38:9:38 | access to local variable a | semmle.label | successor | -| cflow.cs:9:13:9:39 | call to method Switch | cflow.cs:9:9:9:39 | ... = ... | semmle.label | successor | -| cflow.cs:9:38:9:38 | access to local variable a | cflow.cs:9:13:9:39 | call to method Switch | semmle.label | successor | -| cflow.cs:11:9:12:49 | if (...) ... | cflow.cs:11:13:11:13 | access to local variable a | semmle.label | successor | -| cflow.cs:11:13:11:13 | access to local variable a | cflow.cs:11:17:11:17 | 3 | semmle.label | successor | -| cflow.cs:11:13:11:17 | ... > ... | cflow.cs:12:13:12:49 | ...; | semmle.label | true | -| cflow.cs:11:13:11:17 | ... > ... | cflow.cs:14:9:17:9 | while (...) ... | semmle.label | false | -| cflow.cs:11:17:11:17 | 3 | cflow.cs:11:13:11:17 | ... > ... | semmle.label | successor | -| cflow.cs:12:13:12:48 | call to method WriteLine | cflow.cs:14:9:17:9 | while (...) ... | semmle.label | successor | -| cflow.cs:12:13:12:49 | ...; | cflow.cs:12:31:12:47 | "more than a few" | semmle.label | successor | -| cflow.cs:12:31:12:47 | "more than a few" | cflow.cs:12:13:12:48 | call to method WriteLine | semmle.label | successor | -| cflow.cs:14:9:17:9 | while (...) ... | cflow.cs:14:16:14:16 | access to local variable a | semmle.label | successor | -| cflow.cs:14:16:14:16 | access to local variable a | cflow.cs:14:20:14:20 | 0 | semmle.label | successor | -| cflow.cs:14:16:14:20 | ... > ... | cflow.cs:15:9:17:9 | {...} | semmle.label | true | -| cflow.cs:14:16:14:20 | ... > ... | cflow.cs:19:9:22:25 | do ... while (...); | semmle.label | false | -| cflow.cs:14:20:14:20 | 0 | cflow.cs:14:16:14:20 | ... > ... | semmle.label | successor | -| cflow.cs:15:9:17:9 | {...} | cflow.cs:16:13:16:41 | ...; | semmle.label | successor | -| cflow.cs:16:13:16:40 | call to method WriteLine | cflow.cs:14:16:14:16 | access to local variable a | semmle.label | successor | -| cflow.cs:16:13:16:41 | ...; | cflow.cs:16:31:16:31 | access to local variable a | semmle.label | successor | -| cflow.cs:16:31:16:31 | access to local variable a | cflow.cs:16:31:16:33 | ...-- | semmle.label | successor | -| cflow.cs:16:31:16:33 | ...-- | cflow.cs:16:37:16:39 | 100 | semmle.label | successor | -| cflow.cs:16:31:16:39 | ... * ... | cflow.cs:16:13:16:40 | call to method WriteLine | semmle.label | successor | -| cflow.cs:16:37:16:39 | 100 | cflow.cs:16:31:16:39 | ... * ... | semmle.label | successor | -| cflow.cs:19:9:22:25 | do ... while (...); | cflow.cs:20:9:22:9 | {...} | semmle.label | successor | -| cflow.cs:20:9:22:9 | {...} | cflow.cs:21:13:21:36 | ...; | semmle.label | successor | -| cflow.cs:21:13:21:35 | call to method WriteLine | cflow.cs:22:18:22:18 | access to local variable a | semmle.label | successor | -| cflow.cs:21:13:21:36 | ...; | cflow.cs:21:32:21:32 | access to local variable a | semmle.label | successor | -| cflow.cs:21:31:21:34 | -... | cflow.cs:21:13:21:35 | call to method WriteLine | semmle.label | successor | -| cflow.cs:21:32:21:32 | access to local variable a | cflow.cs:21:32:21:34 | ...++ | semmle.label | successor | -| cflow.cs:21:32:21:34 | ...++ | cflow.cs:21:31:21:34 | -... | semmle.label | successor | -| cflow.cs:22:18:22:18 | access to local variable a | cflow.cs:22:22:22:23 | 10 | semmle.label | successor | -| cflow.cs:22:18:22:23 | ... < ... | cflow.cs:20:9:22:9 | {...} | semmle.label | true | -| cflow.cs:22:18:22:23 | ... < ... | cflow.cs:24:9:34:9 | for (...;...;...) ... | semmle.label | false | -| cflow.cs:22:22:22:23 | 10 | cflow.cs:22:18:22:23 | ... < ... | semmle.label | successor | -| cflow.cs:24:9:34:9 | for (...;...;...) ... | cflow.cs:24:22:24:22 | 1 | semmle.label | successor | -| cflow.cs:24:18:24:22 | Int32 i = ... | cflow.cs:24:25:24:25 | access to local variable i | semmle.label | successor | -| cflow.cs:24:22:24:22 | 1 | cflow.cs:24:18:24:22 | Int32 i = ... | semmle.label | successor | -| cflow.cs:24:25:24:25 | access to local variable i | cflow.cs:24:30:24:31 | 20 | semmle.label | successor | -| cflow.cs:24:25:24:31 | ... <= ... | cflow.cs:5:17:5:20 | exit Main (normal) | semmle.label | false | -| cflow.cs:24:25:24:31 | ... <= ... | cflow.cs:25:9:34:9 | {...} | semmle.label | true | -| cflow.cs:24:30:24:31 | 20 | cflow.cs:24:25:24:31 | ... <= ... | semmle.label | successor | -| cflow.cs:24:34:24:34 | access to local variable i | cflow.cs:24:34:24:36 | ...++ | semmle.label | successor | -| cflow.cs:24:34:24:36 | ...++ | cflow.cs:24:25:24:25 | access to local variable i | semmle.label | successor | -| cflow.cs:25:9:34:9 | {...} | cflow.cs:26:13:33:37 | if (...) ... | semmle.label | successor | -| cflow.cs:26:13:33:37 | if (...) ... | cflow.cs:26:17:26:17 | access to local variable i | semmle.label | successor | -| cflow.cs:26:17:26:17 | access to local variable i | cflow.cs:26:21:26:21 | 3 | semmle.label | successor | -| cflow.cs:26:17:26:21 | ... % ... | cflow.cs:26:26:26:26 | 0 | semmle.label | successor | -| cflow.cs:26:17:26:26 | ... == ... | cflow.cs:26:17:26:40 | [false] ... && ... | semmle.label | false | -| cflow.cs:26:17:26:26 | ... == ... | cflow.cs:26:31:26:31 | access to local variable i | semmle.label | true | -| cflow.cs:26:17:26:40 | [false] ... && ... | cflow.cs:28:18:33:37 | if (...) ... | semmle.label | false | -| cflow.cs:26:17:26:40 | [true] ... && ... | cflow.cs:27:17:27:46 | ...; | semmle.label | true | -| cflow.cs:26:21:26:21 | 3 | cflow.cs:26:17:26:21 | ... % ... | semmle.label | successor | -| cflow.cs:26:26:26:26 | 0 | cflow.cs:26:17:26:26 | ... == ... | semmle.label | successor | -| cflow.cs:26:31:26:31 | access to local variable i | cflow.cs:26:35:26:35 | 5 | semmle.label | successor | -| cflow.cs:26:31:26:35 | ... % ... | cflow.cs:26:40:26:40 | 0 | semmle.label | successor | -| cflow.cs:26:31:26:40 | ... == ... | cflow.cs:26:17:26:40 | [false] ... && ... | semmle.label | false | -| cflow.cs:26:31:26:40 | ... == ... | cflow.cs:26:17:26:40 | [true] ... && ... | semmle.label | true | -| cflow.cs:26:35:26:35 | 5 | cflow.cs:26:31:26:35 | ... % ... | semmle.label | successor | -| cflow.cs:26:40:26:40 | 0 | cflow.cs:26:31:26:40 | ... == ... | semmle.label | successor | -| cflow.cs:27:17:27:45 | call to method WriteLine | cflow.cs:24:34:24:34 | access to local variable i | semmle.label | successor | -| cflow.cs:27:17:27:46 | ...; | cflow.cs:27:35:27:44 | "FizzBuzz" | semmle.label | successor | -| cflow.cs:27:35:27:44 | "FizzBuzz" | cflow.cs:27:17:27:45 | call to method WriteLine | semmle.label | successor | -| cflow.cs:28:18:33:37 | if (...) ... | cflow.cs:28:22:28:22 | access to local variable i | semmle.label | successor | -| cflow.cs:28:22:28:22 | access to local variable i | cflow.cs:28:26:28:26 | 3 | semmle.label | successor | -| cflow.cs:28:22:28:26 | ... % ... | cflow.cs:28:31:28:31 | 0 | semmle.label | successor | -| cflow.cs:28:22:28:31 | ... == ... | cflow.cs:29:17:29:42 | ...; | semmle.label | true | -| cflow.cs:28:22:28:31 | ... == ... | cflow.cs:30:18:33:37 | if (...) ... | semmle.label | false | -| cflow.cs:28:26:28:26 | 3 | cflow.cs:28:22:28:26 | ... % ... | semmle.label | successor | -| cflow.cs:28:31:28:31 | 0 | cflow.cs:28:22:28:31 | ... == ... | semmle.label | successor | -| cflow.cs:29:17:29:41 | call to method WriteLine | cflow.cs:24:34:24:34 | access to local variable i | semmle.label | successor | -| cflow.cs:29:17:29:42 | ...; | cflow.cs:29:35:29:40 | "Fizz" | semmle.label | successor | -| cflow.cs:29:35:29:40 | "Fizz" | cflow.cs:29:17:29:41 | call to method WriteLine | semmle.label | successor | -| cflow.cs:30:18:33:37 | if (...) ... | cflow.cs:30:22:30:22 | access to local variable i | semmle.label | successor | -| cflow.cs:30:22:30:22 | access to local variable i | cflow.cs:30:26:30:26 | 5 | semmle.label | successor | -| cflow.cs:30:22:30:26 | ... % ... | cflow.cs:30:31:30:31 | 0 | semmle.label | successor | -| cflow.cs:30:22:30:31 | ... == ... | cflow.cs:31:17:31:42 | ...; | semmle.label | true | -| cflow.cs:30:22:30:31 | ... == ... | cflow.cs:33:17:33:37 | ...; | semmle.label | false | -| cflow.cs:30:26:30:26 | 5 | cflow.cs:30:22:30:26 | ... % ... | semmle.label | successor | -| cflow.cs:30:31:30:31 | 0 | cflow.cs:30:22:30:31 | ... == ... | semmle.label | successor | -| cflow.cs:31:17:31:41 | call to method WriteLine | cflow.cs:24:34:24:34 | access to local variable i | semmle.label | successor | -| cflow.cs:31:17:31:42 | ...; | cflow.cs:31:35:31:40 | "Buzz" | semmle.label | successor | -| cflow.cs:31:35:31:40 | "Buzz" | cflow.cs:31:17:31:41 | call to method WriteLine | semmle.label | successor | -| cflow.cs:33:17:33:36 | call to method WriteLine | cflow.cs:24:34:24:34 | access to local variable i | semmle.label | successor | -| cflow.cs:33:17:33:37 | ...; | cflow.cs:33:35:33:35 | access to local variable i | semmle.label | successor | -| cflow.cs:33:35:33:35 | access to local variable i | cflow.cs:33:17:33:36 | call to method WriteLine | semmle.label | successor | -| cflow.cs:37:17:37:22 | enter Switch | cflow.cs:38:5:68:5 | {...} | semmle.label | successor | -| cflow.cs:37:17:37:22 | exit Switch (abnormal) | cflow.cs:37:17:37:22 | exit Switch | semmle.label | successor | -| cflow.cs:37:17:37:22 | exit Switch (normal) | cflow.cs:37:17:37:22 | exit Switch | semmle.label | successor | -| cflow.cs:38:5:68:5 | {...} | cflow.cs:39:9:50:9 | switch (...) {...} | semmle.label | successor | -| cflow.cs:39:9:50:9 | switch (...) {...} | cflow.cs:39:17:39:17 | access to parameter a | semmle.label | successor | -| cflow.cs:39:17:39:17 | access to parameter a | cflow.cs:41:13:41:19 | case ...: | semmle.label | successor | -| cflow.cs:41:13:41:19 | case ...: | cflow.cs:41:18:41:18 | 1 | semmle.label | successor | -| cflow.cs:41:18:41:18 | 1 | cflow.cs:42:17:42:39 | ...; | semmle.label | match | -| cflow.cs:41:18:41:18 | 1 | cflow.cs:44:13:44:19 | case ...: | semmle.label | no-match | -| cflow.cs:42:17:42:38 | call to method WriteLine | cflow.cs:43:27:43:27 | 2 | semmle.label | successor | -| cflow.cs:42:17:42:39 | ...; | cflow.cs:42:35:42:37 | "1" | semmle.label | successor | -| cflow.cs:42:35:42:37 | "1" | cflow.cs:42:17:42:38 | call to method WriteLine | semmle.label | successor | -| cflow.cs:43:17:43:28 | goto case ...; | cflow.cs:44:13:44:19 | case ...: | semmle.label | goto(2) | -| cflow.cs:43:27:43:27 | 2 | cflow.cs:43:17:43:28 | goto case ...; | semmle.label | successor | -| cflow.cs:44:13:44:19 | case ...: | cflow.cs:44:18:44:18 | 2 | semmle.label | successor | -| cflow.cs:44:18:44:18 | 2 | cflow.cs:45:17:45:39 | ...; | semmle.label | match | -| cflow.cs:44:18:44:18 | 2 | cflow.cs:47:13:47:19 | case ...: | semmle.label | no-match | -| cflow.cs:45:17:45:38 | call to method WriteLine | cflow.cs:46:27:46:27 | 1 | semmle.label | successor | -| cflow.cs:45:17:45:39 | ...; | cflow.cs:45:35:45:37 | "2" | semmle.label | successor | -| cflow.cs:45:35:45:37 | "2" | cflow.cs:45:17:45:38 | call to method WriteLine | semmle.label | successor | -| cflow.cs:46:17:46:28 | goto case ...; | cflow.cs:41:13:41:19 | case ...: | semmle.label | goto(1) | -| cflow.cs:46:27:46:27 | 1 | cflow.cs:46:17:46:28 | goto case ...; | semmle.label | successor | -| cflow.cs:47:13:47:19 | case ...: | cflow.cs:47:18:47:18 | 3 | semmle.label | successor | -| cflow.cs:47:18:47:18 | 3 | cflow.cs:48:17:48:39 | ...; | semmle.label | match | -| cflow.cs:47:18:47:18 | 3 | cflow.cs:51:9:59:9 | switch (...) {...} | semmle.label | no-match | -| cflow.cs:48:17:48:38 | call to method WriteLine | cflow.cs:49:17:49:22 | break; | semmle.label | successor | -| cflow.cs:48:17:48:39 | ...; | cflow.cs:48:35:48:37 | "3" | semmle.label | successor | -| cflow.cs:48:35:48:37 | "3" | cflow.cs:48:17:48:38 | call to method WriteLine | semmle.label | successor | -| cflow.cs:49:17:49:22 | break; | cflow.cs:51:9:59:9 | switch (...) {...} | semmle.label | break | -| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:51:17:51:17 | access to parameter a | semmle.label | successor | -| cflow.cs:51:17:51:17 | access to parameter a | cflow.cs:53:13:53:20 | case ...: | semmle.label | successor | -| cflow.cs:53:13:53:20 | case ...: | cflow.cs:53:18:53:19 | 42 | semmle.label | successor | -| cflow.cs:53:18:53:19 | 42 | cflow.cs:54:17:54:48 | ...; | semmle.label | match | -| cflow.cs:53:18:53:19 | 42 | cflow.cs:56:13:56:20 | default: | semmle.label | no-match | -| cflow.cs:54:17:54:47 | call to method WriteLine | cflow.cs:55:17:55:22 | break; | semmle.label | successor | -| cflow.cs:54:17:54:48 | ...; | cflow.cs:54:35:54:46 | "The answer" | semmle.label | successor | -| cflow.cs:54:35:54:46 | "The answer" | cflow.cs:54:17:54:47 | call to method WriteLine | semmle.label | successor | -| cflow.cs:55:17:55:22 | break; | cflow.cs:60:9:66:9 | switch (...) {...} | semmle.label | break | -| cflow.cs:56:13:56:20 | default: | cflow.cs:57:17:57:52 | ...; | semmle.label | successor | -| cflow.cs:57:17:57:51 | call to method WriteLine | cflow.cs:58:17:58:22 | break; | semmle.label | successor | -| cflow.cs:57:17:57:52 | ...; | cflow.cs:57:35:57:50 | "Not the answer" | semmle.label | successor | -| cflow.cs:57:35:57:50 | "Not the answer" | cflow.cs:57:17:57:51 | call to method WriteLine | semmle.label | successor | -| cflow.cs:58:17:58:22 | break; | cflow.cs:60:9:66:9 | switch (...) {...} | semmle.label | break | -| cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:60:27:60:31 | this access | semmle.label | successor | -| cflow.cs:60:17:60:32 | call to method Parse | cflow.cs:62:13:62:19 | case ...: | semmle.label | successor | -| cflow.cs:60:27:60:31 | access to field Field | cflow.cs:60:17:60:32 | call to method Parse | semmle.label | successor | -| cflow.cs:60:27:60:31 | this access | cflow.cs:60:27:60:31 | access to field Field | semmle.label | successor | -| cflow.cs:62:13:62:19 | case ...: | cflow.cs:62:18:62:18 | 0 | semmle.label | successor | -| cflow.cs:62:18:62:18 | 0 | cflow.cs:63:17:64:55 | if (...) ... | semmle.label | match | -| cflow.cs:62:18:62:18 | 0 | cflow.cs:67:16:67:16 | access to parameter a | semmle.label | no-match | -| cflow.cs:63:17:64:55 | if (...) ... | cflow.cs:63:23:63:27 | this access | semmle.label | successor | -| cflow.cs:63:21:63:34 | [false] !... | cflow.cs:65:17:65:22 | break; | semmle.label | false | -| cflow.cs:63:21:63:34 | [true] !... | cflow.cs:64:27:64:54 | object creation of type NullReferenceException | semmle.label | true | -| cflow.cs:63:23:63:27 | access to field Field | cflow.cs:63:32:63:33 | "" | semmle.label | successor | -| cflow.cs:63:23:63:27 | this access | cflow.cs:63:23:63:27 | access to field Field | semmle.label | successor | -| cflow.cs:63:23:63:33 | ... == ... | cflow.cs:63:21:63:34 | [false] !... | semmle.label | true | -| cflow.cs:63:23:63:33 | ... == ... | cflow.cs:63:21:63:34 | [true] !... | semmle.label | false | -| cflow.cs:63:32:63:33 | "" | cflow.cs:63:23:63:33 | ... == ... | semmle.label | successor | -| cflow.cs:64:21:64:55 | throw ...; | cflow.cs:37:17:37:22 | exit Switch (abnormal) | semmle.label | exception(NullReferenceException) | -| cflow.cs:64:27:64:54 | object creation of type NullReferenceException | cflow.cs:64:21:64:55 | throw ...; | semmle.label | successor | -| cflow.cs:65:17:65:22 | break; | cflow.cs:67:16:67:16 | access to parameter a | semmle.label | break | -| cflow.cs:67:9:67:17 | return ...; | cflow.cs:37:17:37:22 | exit Switch (normal) | semmle.label | return | -| cflow.cs:67:16:67:16 | access to parameter a | cflow.cs:67:9:67:17 | return ...; | semmle.label | successor | -| cflow.cs:70:18:70:18 | enter M | cflow.cs:71:5:82:5 | {...} | semmle.label | successor | -| cflow.cs:70:18:70:18 | exit M (normal) | cflow.cs:70:18:70:18 | exit M | semmle.label | successor | -| cflow.cs:71:5:82:5 | {...} | cflow.cs:72:9:73:19 | if (...) ... | semmle.label | successor | -| cflow.cs:72:9:73:19 | if (...) ... | cflow.cs:72:13:72:13 | access to parameter s | semmle.label | successor | -| cflow.cs:72:13:72:13 | access to parameter s | cflow.cs:72:18:72:21 | null | semmle.label | successor | -| cflow.cs:72:13:72:21 | ... == ... | cflow.cs:73:13:73:19 | return ...; | semmle.label | true | -| cflow.cs:72:13:72:21 | ... == ... | cflow.cs:74:9:81:9 | if (...) ... | semmle.label | false | -| cflow.cs:72:18:72:21 | null | cflow.cs:72:13:72:21 | ... == ... | semmle.label | successor | -| cflow.cs:73:13:73:19 | return ...; | cflow.cs:70:18:70:18 | exit M (normal) | semmle.label | return | -| cflow.cs:74:9:81:9 | if (...) ... | cflow.cs:74:13:74:13 | access to parameter s | semmle.label | successor | -| cflow.cs:74:13:74:13 | access to parameter s | cflow.cs:74:13:74:20 | access to property Length | semmle.label | successor | -| cflow.cs:74:13:74:20 | access to property Length | cflow.cs:74:24:74:24 | 0 | semmle.label | successor | -| cflow.cs:74:13:74:24 | ... > ... | cflow.cs:75:9:77:9 | {...} | semmle.label | true | -| cflow.cs:74:13:74:24 | ... > ... | cflow.cs:79:9:81:9 | {...} | semmle.label | false | -| cflow.cs:74:24:74:24 | 0 | cflow.cs:74:13:74:24 | ... > ... | semmle.label | successor | -| cflow.cs:75:9:77:9 | {...} | cflow.cs:76:13:76:33 | ...; | semmle.label | successor | -| cflow.cs:76:13:76:32 | call to method WriteLine | cflow.cs:70:18:70:18 | exit M (normal) | semmle.label | successor | -| cflow.cs:76:13:76:33 | ...; | cflow.cs:76:31:76:31 | access to parameter s | semmle.label | successor | -| cflow.cs:76:31:76:31 | access to parameter s | cflow.cs:76:13:76:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:79:9:81:9 | {...} | cflow.cs:80:13:80:48 | ...; | semmle.label | successor | -| cflow.cs:80:13:80:47 | call to method WriteLine | cflow.cs:70:18:70:18 | exit M (normal) | semmle.label | successor | -| cflow.cs:80:13:80:48 | ...; | cflow.cs:80:31:80:46 | "" | semmle.label | successor | -| cflow.cs:80:31:80:46 | "" | cflow.cs:80:13:80:47 | call to method WriteLine | semmle.label | successor | -| cflow.cs:84:18:84:19 | enter M2 | cflow.cs:85:5:88:5 | {...} | semmle.label | successor | -| cflow.cs:84:18:84:19 | exit M2 (normal) | cflow.cs:84:18:84:19 | exit M2 | semmle.label | successor | -| cflow.cs:85:5:88:5 | {...} | cflow.cs:86:9:87:33 | if (...) ... | semmle.label | successor | -| cflow.cs:86:9:87:33 | if (...) ... | cflow.cs:86:13:86:13 | access to parameter s | semmle.label | successor | -| cflow.cs:86:13:86:13 | access to parameter s | cflow.cs:86:18:86:21 | null | semmle.label | successor | -| cflow.cs:86:13:86:21 | ... != ... | cflow.cs:86:13:86:37 | [false] ... && ... | semmle.label | false | -| cflow.cs:86:13:86:21 | ... != ... | cflow.cs:86:26:86:26 | access to parameter s | semmle.label | true | -| cflow.cs:86:13:86:37 | [false] ... && ... | cflow.cs:84:18:84:19 | exit M2 (normal) | semmle.label | false | -| cflow.cs:86:13:86:37 | [true] ... && ... | cflow.cs:87:13:87:33 | ...; | semmle.label | true | -| cflow.cs:86:18:86:21 | null | cflow.cs:86:13:86:21 | ... != ... | semmle.label | successor | -| cflow.cs:86:26:86:26 | access to parameter s | cflow.cs:86:26:86:33 | access to property Length | semmle.label | successor | -| cflow.cs:86:26:86:33 | access to property Length | cflow.cs:86:37:86:37 | 0 | semmle.label | successor | -| cflow.cs:86:26:86:37 | ... > ... | cflow.cs:86:13:86:37 | [false] ... && ... | semmle.label | false | -| cflow.cs:86:26:86:37 | ... > ... | cflow.cs:86:13:86:37 | [true] ... && ... | semmle.label | true | -| cflow.cs:86:37:86:37 | 0 | cflow.cs:86:26:86:37 | ... > ... | semmle.label | successor | -| cflow.cs:87:13:87:32 | call to method WriteLine | cflow.cs:84:18:84:19 | exit M2 (normal) | semmle.label | successor | -| cflow.cs:87:13:87:33 | ...; | cflow.cs:87:31:87:31 | access to parameter s | semmle.label | successor | -| cflow.cs:87:31:87:31 | access to parameter s | cflow.cs:87:13:87:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:90:18:90:19 | enter M3 | cflow.cs:91:5:104:5 | {...} | semmle.label | successor | -| cflow.cs:90:18:90:19 | exit M3 (abnormal) | cflow.cs:90:18:90:19 | exit M3 | semmle.label | successor | -| cflow.cs:90:18:90:19 | exit M3 (normal) | cflow.cs:90:18:90:19 | exit M3 | semmle.label | successor | -| cflow.cs:91:5:104:5 | {...} | cflow.cs:92:9:93:49 | if (...) ... | semmle.label | successor | -| cflow.cs:92:9:93:49 | if (...) ... | cflow.cs:92:20:92:20 | access to parameter s | semmle.label | successor | -| cflow.cs:92:13:92:27 | call to method Equals | cflow.cs:93:45:93:47 | "s" | semmle.label | true | -| cflow.cs:92:13:92:27 | call to method Equals | cflow.cs:94:9:94:29 | ...; | semmle.label | false | -| cflow.cs:92:20:92:20 | access to parameter s | cflow.cs:92:23:92:26 | null | semmle.label | successor | -| cflow.cs:92:23:92:26 | null | cflow.cs:92:13:92:27 | call to method Equals | semmle.label | successor | -| cflow.cs:93:13:93:49 | throw ...; | cflow.cs:90:18:90:19 | exit M3 (abnormal) | semmle.label | exception(ArgumentNullException) | -| cflow.cs:93:19:93:48 | object creation of type ArgumentNullException | cflow.cs:93:13:93:49 | throw ...; | semmle.label | successor | -| cflow.cs:93:45:93:47 | "s" | cflow.cs:93:19:93:48 | object creation of type ArgumentNullException | semmle.label | successor | -| cflow.cs:94:9:94:28 | call to method WriteLine | cflow.cs:96:9:97:55 | if (...) ... | semmle.label | successor | -| cflow.cs:94:9:94:29 | ...; | cflow.cs:94:27:94:27 | access to parameter s | semmle.label | successor | -| cflow.cs:94:27:94:27 | access to parameter s | cflow.cs:94:9:94:28 | call to method WriteLine | semmle.label | successor | -| cflow.cs:96:9:97:55 | if (...) ... | cflow.cs:96:13:96:17 | this access | semmle.label | successor | -| cflow.cs:96:13:96:17 | access to field Field | cflow.cs:96:22:96:25 | null | semmle.label | successor | -| cflow.cs:96:13:96:17 | this access | cflow.cs:96:13:96:17 | access to field Field | semmle.label | successor | -| cflow.cs:96:13:96:25 | ... != ... | cflow.cs:97:13:97:55 | ...; | semmle.label | true | -| cflow.cs:96:13:96:25 | ... != ... | cflow.cs:99:9:100:42 | if (...) ... | semmle.label | false | -| cflow.cs:96:22:96:25 | null | cflow.cs:96:13:96:25 | ... != ... | semmle.label | successor | -| cflow.cs:97:13:97:54 | call to method WriteLine | cflow.cs:99:9:100:42 | if (...) ... | semmle.label | successor | -| cflow.cs:97:13:97:55 | ...; | cflow.cs:97:31:97:47 | object creation of type ControlFlow | semmle.label | successor | -| cflow.cs:97:31:97:47 | object creation of type ControlFlow | cflow.cs:97:31:97:53 | access to field Field | semmle.label | successor | -| cflow.cs:97:31:97:53 | access to field Field | cflow.cs:97:13:97:54 | call to method WriteLine | semmle.label | successor | -| cflow.cs:99:9:100:42 | if (...) ... | cflow.cs:99:13:99:17 | this access | semmle.label | successor | -| cflow.cs:99:13:99:17 | access to field Field | cflow.cs:99:22:99:25 | null | semmle.label | successor | -| cflow.cs:99:13:99:17 | this access | cflow.cs:99:13:99:17 | access to field Field | semmle.label | successor | -| cflow.cs:99:13:99:25 | ... != ... | cflow.cs:100:13:100:42 | ...; | semmle.label | true | -| cflow.cs:99:13:99:25 | ... != ... | cflow.cs:102:9:103:36 | if (...) ... | semmle.label | false | -| cflow.cs:99:22:99:25 | null | cflow.cs:99:13:99:25 | ... != ... | semmle.label | successor | -| cflow.cs:100:13:100:41 | call to method WriteLine | cflow.cs:102:9:103:36 | if (...) ... | semmle.label | successor | -| cflow.cs:100:13:100:42 | ...; | cflow.cs:100:31:100:34 | this access | semmle.label | successor | -| cflow.cs:100:31:100:34 | this access | cflow.cs:100:31:100:40 | access to field Field | semmle.label | successor | -| cflow.cs:100:31:100:40 | access to field Field | cflow.cs:100:13:100:41 | call to method WriteLine | semmle.label | successor | -| cflow.cs:102:9:103:36 | if (...) ... | cflow.cs:102:13:102:16 | this access | semmle.label | successor | -| cflow.cs:102:13:102:16 | this access | cflow.cs:102:13:102:21 | access to property Prop | semmle.label | successor | -| cflow.cs:102:13:102:21 | access to property Prop | cflow.cs:102:26:102:29 | null | semmle.label | successor | -| cflow.cs:102:13:102:29 | ... != ... | cflow.cs:90:18:90:19 | exit M3 (normal) | semmle.label | false | -| cflow.cs:102:13:102:29 | ... != ... | cflow.cs:103:13:103:36 | ...; | semmle.label | true | -| cflow.cs:102:26:102:29 | null | cflow.cs:102:13:102:29 | ... != ... | semmle.label | successor | -| cflow.cs:103:13:103:35 | call to method WriteLine | cflow.cs:90:18:90:19 | exit M3 (normal) | semmle.label | successor | -| cflow.cs:103:13:103:36 | ...; | cflow.cs:103:31:103:34 | this access | semmle.label | successor | -| cflow.cs:103:31:103:34 | access to property Prop | cflow.cs:103:13:103:35 | call to method WriteLine | semmle.label | successor | -| cflow.cs:103:31:103:34 | this access | cflow.cs:103:31:103:34 | access to property Prop | semmle.label | successor | -| cflow.cs:106:18:106:19 | enter M4 | cflow.cs:107:5:117:5 | {...} | semmle.label | successor | -| cflow.cs:106:18:106:19 | exit M4 (normal) | cflow.cs:106:18:106:19 | exit M4 | semmle.label | successor | -| cflow.cs:107:5:117:5 | {...} | cflow.cs:108:9:115:9 | if (...) ... | semmle.label | successor | -| cflow.cs:108:9:115:9 | if (...) ... | cflow.cs:108:13:108:13 | access to parameter s | semmle.label | successor | -| cflow.cs:108:13:108:13 | access to parameter s | cflow.cs:108:18:108:21 | null | semmle.label | successor | -| cflow.cs:108:13:108:21 | ... != ... | cflow.cs:109:9:115:9 | {...} | semmle.label | true | -| cflow.cs:108:13:108:21 | ... != ... | cflow.cs:116:9:116:29 | ...; | semmle.label | false | -| cflow.cs:108:18:108:21 | null | cflow.cs:108:13:108:21 | ... != ... | semmle.label | successor | -| cflow.cs:109:9:115:9 | {...} | cflow.cs:110:13:113:13 | while (...) ... | semmle.label | successor | -| cflow.cs:110:13:113:13 | while (...) ... | cflow.cs:110:20:110:23 | true | semmle.label | successor | -| cflow.cs:110:20:110:23 | true | cflow.cs:111:13:113:13 | {...} | semmle.label | true | -| cflow.cs:111:13:113:13 | {...} | cflow.cs:112:17:112:37 | ...; | semmle.label | successor | -| cflow.cs:112:17:112:36 | call to method WriteLine | cflow.cs:110:20:110:23 | true | semmle.label | successor | -| cflow.cs:112:17:112:37 | ...; | cflow.cs:112:35:112:35 | access to parameter s | semmle.label | successor | -| cflow.cs:112:35:112:35 | access to parameter s | cflow.cs:112:17:112:36 | call to method WriteLine | semmle.label | successor | -| cflow.cs:116:9:116:28 | call to method WriteLine | cflow.cs:106:18:106:19 | exit M4 (normal) | semmle.label | successor | -| cflow.cs:116:9:116:29 | ...; | cflow.cs:116:27:116:27 | access to parameter s | semmle.label | successor | -| cflow.cs:116:27:116:27 | access to parameter s | cflow.cs:116:9:116:28 | call to method WriteLine | semmle.label | successor | -| cflow.cs:119:20:119:21 | enter M5 | cflow.cs:120:5:124:5 | {...} | semmle.label | successor | -| cflow.cs:119:20:119:21 | exit M5 (normal) | cflow.cs:119:20:119:21 | exit M5 | semmle.label | successor | -| cflow.cs:120:5:124:5 | {...} | cflow.cs:121:9:121:18 | ... ...; | semmle.label | successor | -| cflow.cs:121:9:121:18 | ... ...; | cflow.cs:121:17:121:17 | access to parameter s | semmle.label | successor | -| cflow.cs:121:13:121:17 | String x = ... | cflow.cs:122:9:122:20 | ...; | semmle.label | successor | -| cflow.cs:121:17:121:17 | access to parameter s | cflow.cs:121:13:121:17 | String x = ... | semmle.label | successor | -| cflow.cs:122:9:122:19 | ... = ... | cflow.cs:123:16:123:16 | access to local variable x | semmle.label | successor | -| cflow.cs:122:9:122:20 | ...; | cflow.cs:122:13:122:13 | access to local variable x | semmle.label | successor | -| cflow.cs:122:13:122:13 | access to local variable x | cflow.cs:122:17:122:19 | " " | semmle.label | successor | -| cflow.cs:122:13:122:19 | ... + ... | cflow.cs:122:9:122:19 | ... = ... | semmle.label | successor | -| cflow.cs:122:17:122:19 | " " | cflow.cs:122:13:122:19 | ... + ... | semmle.label | successor | -| cflow.cs:123:9:123:17 | return ...; | cflow.cs:119:20:119:21 | exit M5 (normal) | semmle.label | return | -| cflow.cs:123:16:123:16 | access to local variable x | cflow.cs:123:9:123:17 | return ...; | semmle.label | successor | -| cflow.cs:127:19:127:21 | enter get_Prop | cflow.cs:127:23:127:60 | {...} | semmle.label | successor | -| cflow.cs:127:19:127:21 | exit get_Prop (normal) | cflow.cs:127:19:127:21 | exit get_Prop | semmle.label | successor | -| cflow.cs:127:23:127:60 | {...} | cflow.cs:127:32:127:36 | this access | semmle.label | successor | -| cflow.cs:127:25:127:58 | return ...; | cflow.cs:127:19:127:21 | exit get_Prop (normal) | semmle.label | return | -| cflow.cs:127:32:127:36 | access to field Field | cflow.cs:127:41:127:44 | null | semmle.label | successor | -| cflow.cs:127:32:127:36 | this access | cflow.cs:127:32:127:36 | access to field Field | semmle.label | successor | -| cflow.cs:127:32:127:44 | ... == ... | cflow.cs:127:48:127:49 | "" | semmle.label | true | -| cflow.cs:127:32:127:44 | ... == ... | cflow.cs:127:53:127:57 | this access | semmle.label | false | -| cflow.cs:127:32:127:57 | ... ? ... : ... | cflow.cs:127:25:127:58 | return ...; | semmle.label | successor | -| cflow.cs:127:41:127:44 | null | cflow.cs:127:32:127:44 | ... == ... | semmle.label | successor | -| cflow.cs:127:48:127:49 | "" | cflow.cs:127:32:127:57 | ... ? ... : ... | semmle.label | successor | -| cflow.cs:127:53:127:57 | access to field Field | cflow.cs:127:32:127:57 | ... ? ... : ... | semmle.label | successor | -| cflow.cs:127:53:127:57 | this access | cflow.cs:127:53:127:57 | access to field Field | semmle.label | successor | -| cflow.cs:127:62:127:64 | enter set_Prop | cflow.cs:127:66:127:83 | {...} | semmle.label | successor | -| cflow.cs:127:62:127:64 | exit set_Prop (normal) | cflow.cs:127:62:127:64 | exit set_Prop | semmle.label | successor | -| cflow.cs:127:66:127:83 | {...} | cflow.cs:127:68:127:81 | ...; | semmle.label | successor | -| cflow.cs:127:68:127:72 | this access | cflow.cs:127:76:127:80 | access to parameter value | semmle.label | successor | -| cflow.cs:127:68:127:80 | ... = ... | cflow.cs:127:62:127:64 | exit set_Prop (normal) | semmle.label | successor | -| cflow.cs:127:68:127:81 | ...; | cflow.cs:127:68:127:72 | this access | semmle.label | successor | -| cflow.cs:127:76:127:80 | access to parameter value | cflow.cs:127:68:127:80 | ... = ... | semmle.label | successor | -| cflow.cs:129:5:129:15 | call to constructor Object | cflow.cs:130:5:132:5 | {...} | semmle.label | successor | -| cflow.cs:129:5:129:15 | enter ControlFlow | cflow.cs:129:5:129:15 | call to constructor Object | semmle.label | successor | -| cflow.cs:129:5:129:15 | exit ControlFlow (normal) | cflow.cs:129:5:129:15 | exit ControlFlow | semmle.label | successor | -| cflow.cs:130:5:132:5 | {...} | cflow.cs:131:9:131:18 | ...; | semmle.label | successor | -| cflow.cs:131:9:131:13 | this access | cflow.cs:131:17:131:17 | access to parameter s | semmle.label | successor | -| cflow.cs:131:9:131:17 | ... = ... | cflow.cs:129:5:129:15 | exit ControlFlow (normal) | semmle.label | successor | -| cflow.cs:131:9:131:18 | ...; | cflow.cs:131:9:131:13 | this access | semmle.label | successor | -| cflow.cs:131:17:131:17 | access to parameter s | cflow.cs:131:9:131:17 | ... = ... | semmle.label | successor | -| cflow.cs:134:5:134:15 | enter ControlFlow | cflow.cs:134:31:134:31 | access to parameter i | semmle.label | successor | -| cflow.cs:134:5:134:15 | exit ControlFlow (normal) | cflow.cs:134:5:134:15 | exit ControlFlow | semmle.label | successor | -| cflow.cs:134:26:134:29 | call to constructor ControlFlow | cflow.cs:134:39:134:41 | {...} | semmle.label | successor | -| cflow.cs:134:31:134:31 | (...) ... | cflow.cs:134:35:134:36 | "" | semmle.label | successor | -| cflow.cs:134:31:134:31 | access to parameter i | cflow.cs:134:31:134:31 | (...) ... | semmle.label | successor | -| cflow.cs:134:31:134:36 | ... + ... | cflow.cs:134:26:134:29 | call to constructor ControlFlow | semmle.label | successor | -| cflow.cs:134:35:134:36 | "" | cflow.cs:134:31:134:36 | ... + ... | semmle.label | successor | -| cflow.cs:134:39:134:41 | {...} | cflow.cs:134:5:134:15 | exit ControlFlow (normal) | semmle.label | successor | -| cflow.cs:136:12:136:22 | enter ControlFlow | cflow.cs:136:33:136:33 | 0 | semmle.label | successor | -| cflow.cs:136:12:136:22 | exit ControlFlow (normal) | cflow.cs:136:12:136:22 | exit ControlFlow | semmle.label | successor | -| cflow.cs:136:28:136:31 | call to constructor ControlFlow | cflow.cs:136:40:136:42 | {...} | semmle.label | successor | -| cflow.cs:136:33:136:33 | 0 | cflow.cs:136:37:136:37 | 1 | semmle.label | successor | -| cflow.cs:136:33:136:37 | ... + ... | cflow.cs:136:28:136:31 | call to constructor ControlFlow | semmle.label | successor | -| cflow.cs:136:37:136:37 | 1 | cflow.cs:136:33:136:37 | ... + ... | semmle.label | successor | -| cflow.cs:136:40:136:42 | {...} | cflow.cs:136:12:136:22 | exit ControlFlow (normal) | semmle.label | successor | -| cflow.cs:138:40:138:40 | enter + | cflow.cs:139:5:142:5 | {...} | semmle.label | successor | -| cflow.cs:138:40:138:40 | exit + (normal) | cflow.cs:138:40:138:40 | exit + | semmle.label | successor | -| cflow.cs:139:5:142:5 | {...} | cflow.cs:140:9:140:29 | ...; | semmle.label | successor | -| cflow.cs:140:9:140:28 | call to method WriteLine | cflow.cs:141:16:141:16 | access to parameter y | semmle.label | successor | -| cflow.cs:140:9:140:29 | ...; | cflow.cs:140:27:140:27 | access to parameter x | semmle.label | successor | -| cflow.cs:140:27:140:27 | access to parameter x | cflow.cs:140:9:140:28 | call to method WriteLine | semmle.label | successor | -| cflow.cs:141:9:141:17 | return ...; | cflow.cs:138:40:138:40 | exit + (normal) | semmle.label | return | -| cflow.cs:141:16:141:16 | access to parameter y | cflow.cs:141:9:141:17 | return ...; | semmle.label | successor | -| cflow.cs:144:33:144:35 | enter get_Item | cflow.cs:144:37:144:54 | {...} | semmle.label | successor | -| cflow.cs:144:33:144:35 | exit get_Item (normal) | cflow.cs:144:33:144:35 | exit get_Item | semmle.label | successor | -| cflow.cs:144:37:144:54 | {...} | cflow.cs:144:46:144:46 | access to parameter i | semmle.label | successor | -| cflow.cs:144:39:144:52 | return ...; | cflow.cs:144:33:144:35 | exit get_Item (normal) | semmle.label | return | -| cflow.cs:144:46:144:46 | (...) ... | cflow.cs:144:50:144:51 | "" | semmle.label | successor | -| cflow.cs:144:46:144:46 | access to parameter i | cflow.cs:144:46:144:46 | (...) ... | semmle.label | successor | -| cflow.cs:144:46:144:51 | ... + ... | cflow.cs:144:39:144:52 | return ...; | semmle.label | successor | -| cflow.cs:144:50:144:51 | "" | cflow.cs:144:46:144:51 | ... + ... | semmle.label | successor | -| cflow.cs:144:56:144:58 | enter set_Item | cflow.cs:144:60:144:62 | {...} | semmle.label | successor | -| cflow.cs:144:56:144:58 | exit set_Item (normal) | cflow.cs:144:56:144:58 | exit set_Item | semmle.label | successor | -| cflow.cs:144:60:144:62 | {...} | cflow.cs:144:56:144:58 | exit set_Item (normal) | semmle.label | successor | -| cflow.cs:146:10:146:12 | enter For | cflow.cs:147:5:177:5 | {...} | semmle.label | successor | -| cflow.cs:146:10:146:12 | exit For (normal) | cflow.cs:146:10:146:12 | exit For | semmle.label | successor | -| cflow.cs:147:5:177:5 | {...} | cflow.cs:148:9:148:18 | ... ...; | semmle.label | successor | -| cflow.cs:148:9:148:18 | ... ...; | cflow.cs:148:17:148:17 | 0 | semmle.label | successor | -| cflow.cs:148:13:148:17 | Int32 x = ... | cflow.cs:149:9:150:33 | for (...;...;...) ... | semmle.label | successor | -| cflow.cs:148:17:148:17 | 0 | cflow.cs:148:13:148:17 | Int32 x = ... | semmle.label | successor | -| cflow.cs:149:9:150:33 | for (...;...;...) ... | cflow.cs:149:16:149:16 | access to local variable x | semmle.label | successor | -| cflow.cs:149:16:149:16 | access to local variable x | cflow.cs:149:20:149:21 | 10 | semmle.label | successor | -| cflow.cs:149:16:149:21 | ... < ... | cflow.cs:150:13:150:33 | ...; | semmle.label | true | -| cflow.cs:149:16:149:21 | ... < ... | cflow.cs:152:9:157:9 | for (...;...;...) ... | semmle.label | false | -| cflow.cs:149:20:149:21 | 10 | cflow.cs:149:16:149:21 | ... < ... | semmle.label | successor | -| cflow.cs:149:24:149:26 | ++... | cflow.cs:149:16:149:16 | access to local variable x | semmle.label | successor | -| cflow.cs:149:26:149:26 | access to local variable x | cflow.cs:149:24:149:26 | ++... | semmle.label | successor | -| cflow.cs:150:13:150:32 | call to method WriteLine | cflow.cs:149:26:149:26 | access to local variable x | semmle.label | successor | -| cflow.cs:150:13:150:33 | ...; | cflow.cs:150:31:150:31 | access to local variable x | semmle.label | successor | -| cflow.cs:150:31:150:31 | access to local variable x | cflow.cs:150:13:150:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:152:9:157:9 | for (...;...;...) ... | cflow.cs:153:9:157:9 | {...} | semmle.label | successor | -| cflow.cs:152:18:152:18 | access to local variable x | cflow.cs:152:18:152:20 | ...++ | semmle.label | successor | -| cflow.cs:152:18:152:20 | ...++ | cflow.cs:153:9:157:9 | {...} | semmle.label | successor | -| cflow.cs:153:9:157:9 | {...} | cflow.cs:154:13:154:33 | ...; | semmle.label | successor | -| cflow.cs:154:13:154:32 | call to method WriteLine | cflow.cs:155:13:156:22 | if (...) ... | semmle.label | successor | -| cflow.cs:154:13:154:33 | ...; | cflow.cs:154:31:154:31 | access to local variable x | semmle.label | successor | -| cflow.cs:154:31:154:31 | access to local variable x | cflow.cs:154:13:154:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:155:13:156:22 | if (...) ... | cflow.cs:155:17:155:17 | access to local variable x | semmle.label | successor | -| cflow.cs:155:17:155:17 | access to local variable x | cflow.cs:155:21:155:22 | 20 | semmle.label | successor | -| cflow.cs:155:17:155:22 | ... > ... | cflow.cs:152:18:152:18 | access to local variable x | semmle.label | false | -| cflow.cs:155:17:155:22 | ... > ... | cflow.cs:156:17:156:22 | break; | semmle.label | true | -| cflow.cs:155:21:155:22 | 20 | cflow.cs:155:17:155:22 | ... > ... | semmle.label | successor | -| cflow.cs:156:17:156:22 | break; | cflow.cs:159:9:165:9 | for (...;...;...) ... | semmle.label | break | -| cflow.cs:159:9:165:9 | for (...;...;...) ... | cflow.cs:160:9:165:9 | {...} | semmle.label | successor | -| cflow.cs:160:9:165:9 | {...} | cflow.cs:161:13:161:33 | ...; | semmle.label | successor | -| cflow.cs:161:13:161:32 | call to method WriteLine | cflow.cs:162:13:162:16 | ...; | semmle.label | successor | -| cflow.cs:161:13:161:33 | ...; | cflow.cs:161:31:161:31 | access to local variable x | semmle.label | successor | -| cflow.cs:161:31:161:31 | access to local variable x | cflow.cs:161:13:161:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:162:13:162:13 | access to local variable x | cflow.cs:162:13:162:15 | ...++ | semmle.label | successor | -| cflow.cs:162:13:162:15 | ...++ | cflow.cs:163:13:164:22 | if (...) ... | semmle.label | successor | -| cflow.cs:162:13:162:16 | ...; | cflow.cs:162:13:162:13 | access to local variable x | semmle.label | successor | -| cflow.cs:163:13:164:22 | if (...) ... | cflow.cs:163:17:163:17 | access to local variable x | semmle.label | successor | -| cflow.cs:163:17:163:17 | access to local variable x | cflow.cs:163:21:163:22 | 30 | semmle.label | successor | -| cflow.cs:163:17:163:22 | ... > ... | cflow.cs:160:9:165:9 | {...} | semmle.label | false | -| cflow.cs:163:17:163:22 | ... > ... | cflow.cs:164:17:164:22 | break; | semmle.label | true | -| cflow.cs:163:21:163:22 | 30 | cflow.cs:163:17:163:22 | ... > ... | semmle.label | successor | -| cflow.cs:164:17:164:22 | break; | cflow.cs:167:9:171:9 | for (...;...;...) ... | semmle.label | break | -| cflow.cs:167:9:171:9 | for (...;...;...) ... | cflow.cs:167:16:167:16 | access to local variable x | semmle.label | successor | -| cflow.cs:167:16:167:16 | access to local variable x | cflow.cs:167:20:167:21 | 40 | semmle.label | successor | -| cflow.cs:167:16:167:21 | ... < ... | cflow.cs:168:9:171:9 | {...} | semmle.label | true | -| cflow.cs:167:16:167:21 | ... < ... | cflow.cs:173:9:176:9 | for (...;...;...) ... | semmle.label | false | -| cflow.cs:167:20:167:21 | 40 | cflow.cs:167:16:167:21 | ... < ... | semmle.label | successor | -| cflow.cs:168:9:171:9 | {...} | cflow.cs:169:13:169:33 | ...; | semmle.label | successor | -| cflow.cs:169:13:169:32 | call to method WriteLine | cflow.cs:170:13:170:16 | ...; | semmle.label | successor | -| cflow.cs:169:13:169:33 | ...; | cflow.cs:169:31:169:31 | access to local variable x | semmle.label | successor | -| cflow.cs:169:31:169:31 | access to local variable x | cflow.cs:169:13:169:32 | call to method WriteLine | semmle.label | successor | -| cflow.cs:170:13:170:13 | access to local variable x | cflow.cs:170:13:170:15 | ...++ | semmle.label | successor | -| cflow.cs:170:13:170:15 | ...++ | cflow.cs:167:16:167:16 | access to local variable x | semmle.label | successor | -| cflow.cs:170:13:170:16 | ...; | cflow.cs:170:13:170:13 | access to local variable x | semmle.label | successor | -| cflow.cs:173:9:176:9 | for (...;...;...) ... | cflow.cs:173:22:173:22 | 0 | semmle.label | successor | -| cflow.cs:173:18:173:22 | Int32 i = ... | cflow.cs:173:29:173:29 | 0 | semmle.label | successor | -| cflow.cs:173:22:173:22 | 0 | cflow.cs:173:18:173:22 | Int32 i = ... | semmle.label | successor | -| cflow.cs:173:25:173:29 | Int32 j = ... | cflow.cs:173:32:173:32 | access to local variable i | semmle.label | successor | -| cflow.cs:173:29:173:29 | 0 | cflow.cs:173:25:173:29 | Int32 j = ... | semmle.label | successor | -| cflow.cs:173:32:173:32 | access to local variable i | cflow.cs:173:36:173:36 | access to local variable j | semmle.label | successor | -| cflow.cs:173:32:173:36 | ... + ... | cflow.cs:173:40:173:41 | 10 | semmle.label | successor | -| cflow.cs:173:32:173:41 | ... < ... | cflow.cs:146:10:146:12 | exit For (normal) | semmle.label | false | -| cflow.cs:173:32:173:41 | ... < ... | cflow.cs:174:9:176:9 | {...} | semmle.label | true | -| cflow.cs:173:36:173:36 | access to local variable j | cflow.cs:173:32:173:36 | ... + ... | semmle.label | successor | -| cflow.cs:173:40:173:41 | 10 | cflow.cs:173:32:173:41 | ... < ... | semmle.label | successor | -| cflow.cs:173:44:173:44 | access to local variable i | cflow.cs:173:44:173:46 | ...++ | semmle.label | successor | -| cflow.cs:173:44:173:46 | ...++ | cflow.cs:173:49:173:49 | access to local variable j | semmle.label | successor | -| cflow.cs:173:49:173:49 | access to local variable j | cflow.cs:173:49:173:51 | ...++ | semmle.label | successor | -| cflow.cs:173:49:173:51 | ...++ | cflow.cs:173:32:173:32 | access to local variable i | semmle.label | successor | -| cflow.cs:174:9:176:9 | {...} | cflow.cs:175:13:175:37 | ...; | semmle.label | successor | -| cflow.cs:175:13:175:36 | call to method WriteLine | cflow.cs:173:44:173:44 | access to local variable i | semmle.label | successor | -| cflow.cs:175:13:175:37 | ...; | cflow.cs:175:31:175:31 | access to local variable i | semmle.label | successor | -| cflow.cs:175:31:175:31 | access to local variable i | cflow.cs:175:35:175:35 | access to local variable j | semmle.label | successor | -| cflow.cs:175:31:175:35 | ... + ... | cflow.cs:175:13:175:36 | call to method WriteLine | semmle.label | successor | -| cflow.cs:175:35:175:35 | access to local variable j | cflow.cs:175:31:175:35 | ... + ... | semmle.label | successor | -| cflow.cs:179:10:179:16 | enter Lambdas | cflow.cs:180:5:183:5 | {...} | semmle.label | successor | -| cflow.cs:179:10:179:16 | exit Lambdas (normal) | cflow.cs:179:10:179:16 | exit Lambdas | semmle.label | successor | -| cflow.cs:180:5:183:5 | {...} | cflow.cs:181:9:181:38 | ... ...; | semmle.label | successor | -| cflow.cs:181:9:181:38 | ... ...; | cflow.cs:181:28:181:37 | (...) => ... | semmle.label | successor | -| cflow.cs:181:24:181:37 | Func y = ... | cflow.cs:182:9:182:62 | ... ...; | semmle.label | successor | -| cflow.cs:181:28:181:37 | (...) => ... | cflow.cs:181:24:181:37 | Func y = ... | semmle.label | successor | -| cflow.cs:181:28:181:37 | enter (...) => ... | cflow.cs:181:33:181:33 | access to parameter x | semmle.label | successor | -| cflow.cs:181:28:181:37 | exit (...) => ... (normal) | cflow.cs:181:28:181:37 | exit (...) => ... | semmle.label | successor | -| cflow.cs:181:33:181:33 | access to parameter x | cflow.cs:181:37:181:37 | 1 | semmle.label | successor | -| cflow.cs:181:33:181:37 | ... + ... | cflow.cs:181:28:181:37 | exit (...) => ... (normal) | semmle.label | successor | -| cflow.cs:181:37:181:37 | 1 | cflow.cs:181:33:181:37 | ... + ... | semmle.label | successor | -| cflow.cs:182:9:182:62 | ... ...; | cflow.cs:182:28:182:61 | delegate(...) { ... } | semmle.label | successor | -| cflow.cs:182:24:182:61 | Func z = ... | cflow.cs:179:10:179:16 | exit Lambdas (normal) | semmle.label | successor | -| cflow.cs:182:28:182:61 | delegate(...) { ... } | cflow.cs:182:24:182:61 | Func z = ... | semmle.label | successor | -| cflow.cs:182:28:182:61 | enter delegate(...) { ... } | cflow.cs:182:45:182:61 | {...} | semmle.label | successor | -| cflow.cs:182:28:182:61 | exit delegate(...) { ... } (normal) | cflow.cs:182:28:182:61 | exit delegate(...) { ... } | semmle.label | successor | -| cflow.cs:182:45:182:61 | {...} | cflow.cs:182:54:182:54 | access to parameter x | semmle.label | successor | -| cflow.cs:182:47:182:59 | return ...; | cflow.cs:182:28:182:61 | exit delegate(...) { ... } (normal) | semmle.label | return | -| cflow.cs:182:54:182:54 | access to parameter x | cflow.cs:182:58:182:58 | 1 | semmle.label | successor | -| cflow.cs:182:54:182:58 | ... + ... | cflow.cs:182:47:182:59 | return ...; | semmle.label | successor | -| cflow.cs:182:58:182:58 | 1 | cflow.cs:182:54:182:58 | ... + ... | semmle.label | successor | -| cflow.cs:185:10:185:18 | enter LogicalOr | cflow.cs:186:5:191:5 | {...} | semmle.label | successor | -| cflow.cs:185:10:185:18 | exit LogicalOr (normal) | cflow.cs:185:10:185:18 | exit LogicalOr | semmle.label | successor | -| cflow.cs:186:5:191:5 | {...} | cflow.cs:187:9:190:52 | if (...) ... | semmle.label | successor | -| cflow.cs:187:9:190:52 | if (...) ... | cflow.cs:187:13:187:13 | 1 | semmle.label | successor | -| cflow.cs:187:13:187:13 | 1 | cflow.cs:187:18:187:18 | 2 | semmle.label | successor | -| cflow.cs:187:13:187:18 | ... == ... | cflow.cs:187:23:187:23 | 2 | semmle.label | false | -| cflow.cs:187:13:187:28 | [false] ... \|\| ... | cflow.cs:187:34:187:34 | 1 | semmle.label | false | -| cflow.cs:187:13:187:50 | [false] ... \|\| ... | cflow.cs:190:13:190:52 | ...; | semmle.label | false | -| cflow.cs:187:18:187:18 | 2 | cflow.cs:187:13:187:18 | ... == ... | semmle.label | successor | -| cflow.cs:187:23:187:23 | 2 | cflow.cs:187:28:187:28 | 3 | semmle.label | successor | -| cflow.cs:187:23:187:28 | ... == ... | cflow.cs:187:13:187:28 | [false] ... \|\| ... | semmle.label | false | -| cflow.cs:187:28:187:28 | 3 | cflow.cs:187:23:187:28 | ... == ... | semmle.label | successor | -| cflow.cs:187:34:187:34 | 1 | cflow.cs:187:39:187:39 | 3 | semmle.label | successor | -| cflow.cs:187:34:187:39 | ... == ... | cflow.cs:187:34:187:49 | [false] ... && ... | semmle.label | false | -| cflow.cs:187:34:187:49 | [false] ... && ... | cflow.cs:187:13:187:50 | [false] ... \|\| ... | semmle.label | false | -| cflow.cs:187:39:187:39 | 3 | cflow.cs:187:34:187:39 | ... == ... | semmle.label | successor | -| cflow.cs:190:13:190:51 | call to method WriteLine | cflow.cs:185:10:185:18 | exit LogicalOr (normal) | semmle.label | successor | -| cflow.cs:190:13:190:52 | ...; | cflow.cs:190:31:190:50 | "This should happen" | semmle.label | successor | -| cflow.cs:190:31:190:50 | "This should happen" | cflow.cs:190:13:190:51 | call to method WriteLine | semmle.label | successor | -| cflow.cs:193:10:193:17 | enter Booleans | cflow.cs:194:5:206:5 | {...} | semmle.label | successor | -| cflow.cs:193:10:193:17 | exit Booleans (abnormal) | cflow.cs:193:10:193:17 | exit Booleans | semmle.label | successor | -| cflow.cs:193:10:193:17 | exit Booleans (normal) | cflow.cs:193:10:193:17 | exit Booleans | semmle.label | successor | -| cflow.cs:194:5:206:5 | {...} | cflow.cs:195:9:195:57 | ... ...; | semmle.label | successor | -| cflow.cs:195:9:195:57 | ... ...; | cflow.cs:195:17:195:21 | this access | semmle.label | successor | -| cflow.cs:195:13:195:56 | Boolean b = ... | cflow.cs:197:9:198:49 | if (...) ... | semmle.label | successor | -| cflow.cs:195:17:195:21 | access to field Field | cflow.cs:195:17:195:28 | access to property Length | semmle.label | successor | -| cflow.cs:195:17:195:21 | this access | cflow.cs:195:17:195:21 | access to field Field | semmle.label | successor | -| cflow.cs:195:17:195:28 | access to property Length | cflow.cs:195:32:195:32 | 0 | semmle.label | successor | -| cflow.cs:195:17:195:32 | ... > ... | cflow.cs:195:17:195:56 | ... && ... | semmle.label | false | -| cflow.cs:195:17:195:32 | ... > ... | cflow.cs:195:39:195:43 | this access | semmle.label | true | -| cflow.cs:195:17:195:56 | ... && ... | cflow.cs:195:13:195:56 | Boolean b = ... | semmle.label | successor | -| cflow.cs:195:32:195:32 | 0 | cflow.cs:195:17:195:32 | ... > ... | semmle.label | successor | -| cflow.cs:195:37:195:56 | !... | cflow.cs:195:17:195:56 | ... && ... | semmle.label | successor | -| cflow.cs:195:39:195:43 | access to field Field | cflow.cs:195:39:195:50 | access to property Length | semmle.label | successor | -| cflow.cs:195:39:195:43 | this access | cflow.cs:195:39:195:43 | access to field Field | semmle.label | successor | -| cflow.cs:195:39:195:50 | access to property Length | cflow.cs:195:55:195:55 | 1 | semmle.label | successor | -| cflow.cs:195:39:195:55 | ... == ... | cflow.cs:195:37:195:56 | !... | semmle.label | successor | -| cflow.cs:195:55:195:55 | 1 | cflow.cs:195:39:195:55 | ... == ... | semmle.label | successor | -| cflow.cs:197:9:198:49 | if (...) ... | cflow.cs:197:15:197:19 | this access | semmle.label | successor | -| cflow.cs:197:13:197:47 | [false] !... | cflow.cs:200:9:205:9 | if (...) ... | semmle.label | false | -| cflow.cs:197:13:197:47 | [true] !... | cflow.cs:198:13:198:49 | ...; | semmle.label | true | -| cflow.cs:197:15:197:19 | access to field Field | cflow.cs:197:15:197:26 | access to property Length | semmle.label | successor | -| cflow.cs:197:15:197:19 | this access | cflow.cs:197:15:197:19 | access to field Field | semmle.label | successor | -| cflow.cs:197:15:197:26 | access to property Length | cflow.cs:197:31:197:31 | 0 | semmle.label | successor | -| cflow.cs:197:15:197:31 | ... == ... | cflow.cs:197:35:197:39 | false | semmle.label | true | -| cflow.cs:197:15:197:31 | ... == ... | cflow.cs:197:43:197:46 | true | semmle.label | false | -| cflow.cs:197:15:197:46 | [false] ... ? ... : ... | cflow.cs:197:13:197:47 | [true] !... | semmle.label | false | -| cflow.cs:197:15:197:46 | [true] ... ? ... : ... | cflow.cs:197:13:197:47 | [false] !... | semmle.label | true | -| cflow.cs:197:31:197:31 | 0 | cflow.cs:197:15:197:31 | ... == ... | semmle.label | successor | -| cflow.cs:197:35:197:39 | false | cflow.cs:197:15:197:46 | [false] ... ? ... : ... | semmle.label | false | -| cflow.cs:197:43:197:46 | true | cflow.cs:197:15:197:46 | [true] ... ? ... : ... | semmle.label | true | -| cflow.cs:198:13:198:48 | ... = ... | cflow.cs:200:9:205:9 | if (...) ... | semmle.label | successor | -| cflow.cs:198:13:198:49 | ...; | cflow.cs:198:17:198:21 | this access | semmle.label | successor | -| cflow.cs:198:17:198:21 | access to field Field | cflow.cs:198:17:198:28 | access to property Length | semmle.label | successor | -| cflow.cs:198:17:198:21 | this access | cflow.cs:198:17:198:21 | access to field Field | semmle.label | successor | -| cflow.cs:198:17:198:28 | access to property Length | cflow.cs:198:33:198:33 | 0 | semmle.label | successor | -| cflow.cs:198:17:198:33 | ... == ... | cflow.cs:198:37:198:41 | false | semmle.label | true | -| cflow.cs:198:17:198:33 | ... == ... | cflow.cs:198:45:198:48 | true | semmle.label | false | -| cflow.cs:198:17:198:48 | ... ? ... : ... | cflow.cs:198:13:198:48 | ... = ... | semmle.label | successor | -| cflow.cs:198:33:198:33 | 0 | cflow.cs:198:17:198:33 | ... == ... | semmle.label | successor | -| cflow.cs:198:37:198:41 | false | cflow.cs:198:17:198:48 | ... ? ... : ... | semmle.label | successor | -| cflow.cs:198:45:198:48 | true | cflow.cs:198:17:198:48 | ... ? ... : ... | semmle.label | successor | -| cflow.cs:200:9:205:9 | if (...) ... | cflow.cs:200:15:200:19 | this access | semmle.label | successor | -| cflow.cs:200:13:200:32 | [false] !... | cflow.cs:200:40:200:44 | this access | semmle.label | false | -| cflow.cs:200:13:200:32 | [true] !... | cflow.cs:200:13:200:62 | [true] ... \|\| ... | semmle.label | true | -| cflow.cs:200:13:200:62 | [false] ... \|\| ... | cflow.cs:193:10:193:17 | exit Booleans (normal) | semmle.label | false | -| cflow.cs:200:13:200:62 | [true] ... \|\| ... | cflow.cs:201:9:205:9 | {...} | semmle.label | true | -| cflow.cs:200:15:200:19 | access to field Field | cflow.cs:200:15:200:26 | access to property Length | semmle.label | successor | -| cflow.cs:200:15:200:19 | this access | cflow.cs:200:15:200:19 | access to field Field | semmle.label | successor | -| cflow.cs:200:15:200:26 | access to property Length | cflow.cs:200:31:200:31 | 0 | semmle.label | successor | -| cflow.cs:200:15:200:31 | ... == ... | cflow.cs:200:13:200:32 | [false] !... | semmle.label | true | -| cflow.cs:200:15:200:31 | ... == ... | cflow.cs:200:13:200:32 | [true] !... | semmle.label | false | -| cflow.cs:200:31:200:31 | 0 | cflow.cs:200:15:200:31 | ... == ... | semmle.label | successor | -| cflow.cs:200:37:200:62 | [false] !... | cflow.cs:200:13:200:62 | [false] ... \|\| ... | semmle.label | false | -| cflow.cs:200:37:200:62 | [true] !... | cflow.cs:200:13:200:62 | [true] ... \|\| ... | semmle.label | true | -| cflow.cs:200:38:200:62 | [false] !... | cflow.cs:200:37:200:62 | [true] !... | semmle.label | false | -| cflow.cs:200:38:200:62 | [true] !... | cflow.cs:200:37:200:62 | [false] !... | semmle.label | true | -| cflow.cs:200:40:200:44 | access to field Field | cflow.cs:200:40:200:51 | access to property Length | semmle.label | successor | -| cflow.cs:200:40:200:44 | this access | cflow.cs:200:40:200:44 | access to field Field | semmle.label | successor | -| cflow.cs:200:40:200:51 | access to property Length | cflow.cs:200:56:200:56 | 1 | semmle.label | successor | -| cflow.cs:200:40:200:56 | ... == ... | cflow.cs:200:40:200:61 | [false] ... && ... | semmle.label | false | -| cflow.cs:200:40:200:56 | ... == ... | cflow.cs:200:61:200:61 | access to local variable b | semmle.label | true | -| cflow.cs:200:40:200:61 | [false] ... && ... | cflow.cs:200:38:200:62 | [true] !... | semmle.label | false | -| cflow.cs:200:40:200:61 | [true] ... && ... | cflow.cs:200:38:200:62 | [false] !... | semmle.label | true | -| cflow.cs:200:56:200:56 | 1 | cflow.cs:200:40:200:56 | ... == ... | semmle.label | successor | -| cflow.cs:200:61:200:61 | access to local variable b | cflow.cs:200:40:200:61 | [false] ... && ... | semmle.label | false | -| cflow.cs:200:61:200:61 | access to local variable b | cflow.cs:200:40:200:61 | [true] ... && ... | semmle.label | true | -| cflow.cs:201:9:205:9 | {...} | cflow.cs:202:13:204:13 | {...} | semmle.label | successor | -| cflow.cs:202:13:204:13 | {...} | cflow.cs:203:23:203:37 | object creation of type Exception | semmle.label | successor | -| cflow.cs:203:17:203:38 | throw ...; | cflow.cs:193:10:193:17 | exit Booleans (abnormal) | semmle.label | exception(Exception) | -| cflow.cs:203:23:203:37 | object creation of type Exception | cflow.cs:203:17:203:38 | throw ...; | semmle.label | successor | -| cflow.cs:208:10:208:11 | enter Do | cflow.cs:209:5:222:5 | {...} | semmle.label | successor | -| cflow.cs:208:10:208:11 | exit Do (normal) | cflow.cs:208:10:208:11 | exit Do | semmle.label | successor | -| cflow.cs:209:5:222:5 | {...} | cflow.cs:210:9:221:36 | do ... while (...); | semmle.label | successor | -| cflow.cs:210:9:221:36 | do ... while (...); | cflow.cs:211:9:221:9 | {...} | semmle.label | successor | -| cflow.cs:211:9:221:9 | {...} | cflow.cs:212:13:212:25 | ...; | semmle.label | successor | -| cflow.cs:212:13:212:17 | access to field Field | cflow.cs:212:22:212:24 | "a" | semmle.label | successor | -| cflow.cs:212:13:212:17 | this access | cflow.cs:212:13:212:17 | access to field Field | semmle.label | successor | -| cflow.cs:212:13:212:17 | this access | cflow.cs:212:13:212:17 | this access | semmle.label | successor | -| cflow.cs:212:13:212:24 | ... + ... | cflow.cs:212:13:212:24 | ... = ... | semmle.label | successor | -| cflow.cs:212:13:212:24 | ... = ... | cflow.cs:213:13:216:13 | if (...) ... | semmle.label | successor | -| cflow.cs:212:13:212:25 | ...; | cflow.cs:212:13:212:17 | this access | semmle.label | successor | -| cflow.cs:212:22:212:24 | "a" | cflow.cs:212:13:212:24 | ... + ... | semmle.label | successor | -| cflow.cs:213:13:216:13 | if (...) ... | cflow.cs:213:17:213:21 | this access | semmle.label | successor | -| cflow.cs:213:17:213:21 | access to field Field | cflow.cs:213:17:213:28 | access to property Length | semmle.label | successor | -| cflow.cs:213:17:213:21 | this access | cflow.cs:213:17:213:21 | access to field Field | semmle.label | successor | -| cflow.cs:213:17:213:28 | access to property Length | cflow.cs:213:32:213:32 | 0 | semmle.label | successor | -| cflow.cs:213:17:213:32 | ... > ... | cflow.cs:214:13:216:13 | {...} | semmle.label | true | -| cflow.cs:213:17:213:32 | ... > ... | cflow.cs:217:13:220:13 | if (...) ... | semmle.label | false | -| cflow.cs:213:32:213:32 | 0 | cflow.cs:213:17:213:32 | ... > ... | semmle.label | successor | -| cflow.cs:214:13:216:13 | {...} | cflow.cs:215:17:215:25 | continue; | semmle.label | successor | -| cflow.cs:215:17:215:25 | continue; | cflow.cs:221:18:221:22 | this access | semmle.label | continue | -| cflow.cs:217:13:220:13 | if (...) ... | cflow.cs:217:17:217:21 | this access | semmle.label | successor | -| cflow.cs:217:17:217:21 | access to field Field | cflow.cs:217:17:217:28 | access to property Length | semmle.label | successor | -| cflow.cs:217:17:217:21 | this access | cflow.cs:217:17:217:21 | access to field Field | semmle.label | successor | -| cflow.cs:217:17:217:28 | access to property Length | cflow.cs:217:32:217:32 | 0 | semmle.label | successor | -| cflow.cs:217:17:217:32 | ... < ... | cflow.cs:218:13:220:13 | {...} | semmle.label | true | -| cflow.cs:217:17:217:32 | ... < ... | cflow.cs:221:18:221:22 | this access | semmle.label | false | -| cflow.cs:217:32:217:32 | 0 | cflow.cs:217:17:217:32 | ... < ... | semmle.label | successor | -| cflow.cs:218:13:220:13 | {...} | cflow.cs:219:17:219:22 | break; | semmle.label | successor | -| cflow.cs:219:17:219:22 | break; | cflow.cs:208:10:208:11 | exit Do (normal) | semmle.label | break | -| cflow.cs:221:18:221:22 | access to field Field | cflow.cs:221:18:221:29 | access to property Length | semmle.label | successor | -| cflow.cs:221:18:221:22 | this access | cflow.cs:221:18:221:22 | access to field Field | semmle.label | successor | -| cflow.cs:221:18:221:29 | access to property Length | cflow.cs:221:33:221:34 | 10 | semmle.label | successor | -| cflow.cs:221:18:221:34 | ... < ... | cflow.cs:208:10:208:11 | exit Do (normal) | semmle.label | false | -| cflow.cs:221:18:221:34 | ... < ... | cflow.cs:211:9:221:9 | {...} | semmle.label | true | -| cflow.cs:221:33:221:34 | 10 | cflow.cs:221:18:221:34 | ... < ... | semmle.label | successor | -| cflow.cs:224:10:224:16 | enter Foreach | cflow.cs:225:5:238:5 | {...} | semmle.label | successor | -| cflow.cs:224:10:224:16 | exit Foreach (normal) | cflow.cs:224:10:224:16 | exit Foreach | semmle.label | successor | -| cflow.cs:225:5:238:5 | {...} | cflow.cs:226:57:226:59 | "a" | semmle.label | successor | -| cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | cflow.cs:224:10:224:16 | exit Foreach (normal) | semmle.label | empty | -| cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | cflow.cs:226:22:226:22 | String x | semmle.label | non-empty | -| cflow.cs:226:22:226:22 | String x | cflow.cs:227:9:237:9 | {...} | semmle.label | successor | -| cflow.cs:226:27:226:64 | call to method Repeat | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | semmle.label | successor | -| cflow.cs:226:57:226:59 | "a" | cflow.cs:226:62:226:63 | 10 | semmle.label | successor | -| cflow.cs:226:62:226:63 | 10 | cflow.cs:226:27:226:64 | call to method Repeat | semmle.label | successor | -| cflow.cs:227:9:237:9 | {...} | cflow.cs:228:13:228:23 | ...; | semmle.label | successor | -| cflow.cs:228:13:228:17 | access to field Field | cflow.cs:228:22:228:22 | access to local variable x | semmle.label | successor | -| cflow.cs:228:13:228:17 | this access | cflow.cs:228:13:228:17 | access to field Field | semmle.label | successor | -| cflow.cs:228:13:228:17 | this access | cflow.cs:228:13:228:17 | this access | semmle.label | successor | -| cflow.cs:228:13:228:22 | ... + ... | cflow.cs:228:13:228:22 | ... = ... | semmle.label | successor | -| cflow.cs:228:13:228:22 | ... = ... | cflow.cs:229:13:232:13 | if (...) ... | semmle.label | successor | -| cflow.cs:228:13:228:23 | ...; | cflow.cs:228:13:228:17 | this access | semmle.label | successor | -| cflow.cs:228:22:228:22 | access to local variable x | cflow.cs:228:13:228:22 | ... + ... | semmle.label | successor | -| cflow.cs:229:13:232:13 | if (...) ... | cflow.cs:229:17:229:21 | this access | semmle.label | successor | -| cflow.cs:229:17:229:21 | access to field Field | cflow.cs:229:17:229:28 | access to property Length | semmle.label | successor | -| cflow.cs:229:17:229:21 | this access | cflow.cs:229:17:229:21 | access to field Field | semmle.label | successor | -| cflow.cs:229:17:229:28 | access to property Length | cflow.cs:229:32:229:32 | 0 | semmle.label | successor | -| cflow.cs:229:17:229:32 | ... > ... | cflow.cs:230:13:232:13 | {...} | semmle.label | true | -| cflow.cs:229:17:229:32 | ... > ... | cflow.cs:233:13:236:13 | if (...) ... | semmle.label | false | -| cflow.cs:229:32:229:32 | 0 | cflow.cs:229:17:229:32 | ... > ... | semmle.label | successor | -| cflow.cs:230:13:232:13 | {...} | cflow.cs:231:17:231:25 | continue; | semmle.label | successor | -| cflow.cs:231:17:231:25 | continue; | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | semmle.label | continue | -| cflow.cs:233:13:236:13 | if (...) ... | cflow.cs:233:17:233:21 | this access | semmle.label | successor | -| cflow.cs:233:17:233:21 | access to field Field | cflow.cs:233:17:233:28 | access to property Length | semmle.label | successor | -| cflow.cs:233:17:233:21 | this access | cflow.cs:233:17:233:21 | access to field Field | semmle.label | successor | -| cflow.cs:233:17:233:28 | access to property Length | cflow.cs:233:32:233:32 | 0 | semmle.label | successor | -| cflow.cs:233:17:233:32 | ... < ... | cflow.cs:226:9:237:9 | foreach (... ... in ...) ... | semmle.label | false | -| cflow.cs:233:17:233:32 | ... < ... | cflow.cs:234:13:236:13 | {...} | semmle.label | true | -| cflow.cs:233:32:233:32 | 0 | cflow.cs:233:17:233:32 | ... < ... | semmle.label | successor | -| cflow.cs:234:13:236:13 | {...} | cflow.cs:235:17:235:22 | break; | semmle.label | successor | -| cflow.cs:235:17:235:22 | break; | cflow.cs:224:10:224:16 | exit Foreach (normal) | semmle.label | break | -| cflow.cs:240:10:240:13 | enter Goto | cflow.cs:241:5:259:5 | {...} | semmle.label | successor | -| cflow.cs:240:10:240:13 | exit Goto (normal) | cflow.cs:240:10:240:13 | exit Goto | semmle.label | successor | -| cflow.cs:241:5:259:5 | {...} | cflow.cs:242:9:242:13 | Label: | semmle.label | successor | -| cflow.cs:242:9:242:13 | Label: | cflow.cs:242:16:242:45 | if (...) ... | semmle.label | successor | -| cflow.cs:242:16:242:45 | if (...) ... | cflow.cs:242:23:242:27 | this access | semmle.label | successor | -| cflow.cs:242:20:242:40 | [false] !... | cflow.cs:244:9:244:41 | if (...) ... | semmle.label | false | -| cflow.cs:242:20:242:40 | [true] !... | cflow.cs:242:43:242:45 | {...} | semmle.label | true | -| cflow.cs:242:21:242:40 | [false] !... | cflow.cs:242:20:242:40 | [true] !... | semmle.label | false | -| cflow.cs:242:21:242:40 | [true] !... | cflow.cs:242:20:242:40 | [false] !... | semmle.label | true | -| cflow.cs:242:23:242:27 | access to field Field | cflow.cs:242:23:242:34 | access to property Length | semmle.label | successor | -| cflow.cs:242:23:242:27 | this access | cflow.cs:242:23:242:27 | access to field Field | semmle.label | successor | -| cflow.cs:242:23:242:34 | access to property Length | cflow.cs:242:39:242:39 | 0 | semmle.label | successor | -| cflow.cs:242:23:242:39 | ... == ... | cflow.cs:242:21:242:40 | [false] !... | semmle.label | true | -| cflow.cs:242:23:242:39 | ... == ... | cflow.cs:242:21:242:40 | [true] !... | semmle.label | false | -| cflow.cs:242:39:242:39 | 0 | cflow.cs:242:23:242:39 | ... == ... | semmle.label | successor | -| cflow.cs:242:43:242:45 | {...} | cflow.cs:244:9:244:41 | if (...) ... | semmle.label | successor | -| cflow.cs:244:9:244:41 | if (...) ... | cflow.cs:244:13:244:17 | this access | semmle.label | successor | -| cflow.cs:244:13:244:17 | access to field Field | cflow.cs:244:13:244:24 | access to property Length | semmle.label | successor | -| cflow.cs:244:13:244:17 | this access | cflow.cs:244:13:244:17 | access to field Field | semmle.label | successor | -| cflow.cs:244:13:244:24 | access to property Length | cflow.cs:244:28:244:28 | 0 | semmle.label | successor | -| cflow.cs:244:13:244:28 | ... > ... | cflow.cs:244:31:244:41 | goto ...; | semmle.label | true | -| cflow.cs:244:13:244:28 | ... > ... | cflow.cs:246:9:258:9 | switch (...) {...} | semmle.label | false | -| cflow.cs:244:28:244:28 | 0 | cflow.cs:244:13:244:28 | ... > ... | semmle.label | successor | -| cflow.cs:244:31:244:41 | goto ...; | cflow.cs:242:9:242:13 | Label: | semmle.label | goto(Label) | -| cflow.cs:246:9:258:9 | switch (...) {...} | cflow.cs:246:17:246:21 | this access | semmle.label | successor | -| cflow.cs:246:17:246:21 | access to field Field | cflow.cs:246:17:246:28 | access to property Length | semmle.label | successor | -| cflow.cs:246:17:246:21 | this access | cflow.cs:246:17:246:21 | access to field Field | semmle.label | successor | -| cflow.cs:246:17:246:28 | access to property Length | cflow.cs:246:32:246:32 | 3 | semmle.label | successor | -| cflow.cs:246:17:246:32 | ... + ... | cflow.cs:248:13:248:19 | case ...: | semmle.label | successor | -| cflow.cs:246:32:246:32 | 3 | cflow.cs:246:17:246:32 | ... + ... | semmle.label | successor | -| cflow.cs:248:13:248:19 | case ...: | cflow.cs:248:18:248:18 | 0 | semmle.label | successor | -| cflow.cs:248:18:248:18 | 0 | cflow.cs:249:17:249:29 | goto default; | semmle.label | match | -| cflow.cs:248:18:248:18 | 0 | cflow.cs:250:13:250:19 | case ...: | semmle.label | no-match | -| cflow.cs:249:17:249:29 | goto default; | cflow.cs:255:13:255:20 | default: | semmle.label | goto(default) | -| cflow.cs:250:13:250:19 | case ...: | cflow.cs:250:18:250:18 | 1 | semmle.label | successor | -| cflow.cs:250:18:250:18 | 1 | cflow.cs:251:17:251:37 | ...; | semmle.label | match | -| cflow.cs:250:18:250:18 | 1 | cflow.cs:253:13:253:19 | case ...: | semmle.label | no-match | -| cflow.cs:251:17:251:36 | call to method WriteLine | cflow.cs:252:17:252:22 | break; | semmle.label | successor | -| cflow.cs:251:17:251:37 | ...; | cflow.cs:251:35:251:35 | 1 | semmle.label | successor | -| cflow.cs:251:35:251:35 | 1 | cflow.cs:251:17:251:36 | call to method WriteLine | semmle.label | successor | -| cflow.cs:252:17:252:22 | break; | cflow.cs:240:10:240:13 | exit Goto (normal) | semmle.label | break | -| cflow.cs:253:13:253:19 | case ...: | cflow.cs:253:18:253:18 | 2 | semmle.label | successor | -| cflow.cs:253:18:253:18 | 2 | cflow.cs:254:17:254:27 | goto ...; | semmle.label | match | -| cflow.cs:253:18:253:18 | 2 | cflow.cs:255:13:255:20 | default: | semmle.label | no-match | -| cflow.cs:254:17:254:27 | goto ...; | cflow.cs:242:9:242:13 | Label: | semmle.label | goto(Label) | -| cflow.cs:255:13:255:20 | default: | cflow.cs:256:17:256:37 | ...; | semmle.label | successor | -| cflow.cs:256:17:256:36 | call to method WriteLine | cflow.cs:257:17:257:22 | break; | semmle.label | successor | -| cflow.cs:256:17:256:37 | ...; | cflow.cs:256:35:256:35 | 0 | semmle.label | successor | -| cflow.cs:256:35:256:35 | 0 | cflow.cs:256:17:256:36 | call to method WriteLine | semmle.label | successor | -| cflow.cs:257:17:257:22 | break; | cflow.cs:240:10:240:13 | exit Goto (normal) | semmle.label | break | -| cflow.cs:261:49:261:53 | enter Yield | cflow.cs:262:5:277:5 | {...} | semmle.label | successor | -| cflow.cs:261:49:261:53 | exit Yield (normal) | cflow.cs:261:49:261:53 | exit Yield | semmle.label | successor | -| cflow.cs:262:5:277:5 | {...} | cflow.cs:263:22:263:22 | 0 | semmle.label | successor | -| cflow.cs:263:9:263:23 | yield return ...; | cflow.cs:264:9:267:9 | for (...;...;...) ... | semmle.label | successor | -| cflow.cs:263:22:263:22 | 0 | cflow.cs:263:9:263:23 | yield return ...; | semmle.label | successor | -| cflow.cs:264:9:267:9 | for (...;...;...) ... | cflow.cs:264:22:264:22 | 1 | semmle.label | successor | -| cflow.cs:264:18:264:22 | Int32 i = ... | cflow.cs:264:25:264:25 | access to local variable i | semmle.label | successor | -| cflow.cs:264:22:264:22 | 1 | cflow.cs:264:18:264:22 | Int32 i = ... | semmle.label | successor | -| cflow.cs:264:25:264:25 | access to local variable i | cflow.cs:264:29:264:30 | 10 | semmle.label | successor | -| cflow.cs:264:25:264:30 | ... < ... | cflow.cs:265:9:267:9 | {...} | semmle.label | true | -| cflow.cs:264:25:264:30 | ... < ... | cflow.cs:268:9:276:9 | try {...} ... | semmle.label | false | -| cflow.cs:264:29:264:30 | 10 | cflow.cs:264:25:264:30 | ... < ... | semmle.label | successor | -| cflow.cs:264:33:264:33 | access to local variable i | cflow.cs:264:33:264:35 | ...++ | semmle.label | successor | -| cflow.cs:264:33:264:35 | ...++ | cflow.cs:264:25:264:25 | access to local variable i | semmle.label | successor | -| cflow.cs:265:9:267:9 | {...} | cflow.cs:266:26:266:26 | access to local variable i | semmle.label | successor | -| cflow.cs:266:13:266:27 | yield return ...; | cflow.cs:264:33:264:33 | access to local variable i | semmle.label | successor | -| cflow.cs:266:26:266:26 | access to local variable i | cflow.cs:266:13:266:27 | yield return ...; | semmle.label | successor | -| cflow.cs:268:9:276:9 | try {...} ... | cflow.cs:269:9:272:9 | {...} | semmle.label | successor | -| cflow.cs:269:9:272:9 | {...} | cflow.cs:270:13:270:24 | yield break; | semmle.label | successor | -| cflow.cs:270:13:270:24 | yield break; | cflow.cs:274:9:276:9 | [finally: return] {...} | semmle.label | return | -| cflow.cs:274:9:276:9 | [finally: return] {...} | cflow.cs:275:13:275:42 | [finally: return] ...; | semmle.label | successor | -| cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | cflow.cs:261:49:261:53 | exit Yield (normal) | semmle.label | return | -| cflow.cs:275:13:275:42 | [finally: return] ...; | cflow.cs:275:31:275:40 | [finally: return] "not dead" | semmle.label | successor | -| cflow.cs:275:31:275:40 | [finally: return] "not dead" | cflow.cs:275:13:275:41 | [finally: return] call to method WriteLine | semmle.label | successor | -| cflow.cs:282:5:282:18 | enter ControlFlowSub | cflow.cs:282:24:282:27 | call to constructor ControlFlow | semmle.label | successor | -| cflow.cs:282:5:282:18 | exit ControlFlowSub (normal) | cflow.cs:282:5:282:18 | exit ControlFlowSub | semmle.label | successor | -| cflow.cs:282:24:282:27 | call to constructor ControlFlow | cflow.cs:282:31:282:33 | {...} | semmle.label | successor | -| cflow.cs:282:31:282:33 | {...} | cflow.cs:282:5:282:18 | exit ControlFlowSub (normal) | semmle.label | successor | -| cflow.cs:284:5:284:18 | enter ControlFlowSub | cflow.cs:284:32:284:35 | call to constructor ControlFlowSub | semmle.label | successor | -| cflow.cs:284:5:284:18 | exit ControlFlowSub (normal) | cflow.cs:284:5:284:18 | exit ControlFlowSub | semmle.label | successor | -| cflow.cs:284:32:284:35 | call to constructor ControlFlowSub | cflow.cs:284:39:284:41 | {...} | semmle.label | successor | -| cflow.cs:284:39:284:41 | {...} | cflow.cs:284:5:284:18 | exit ControlFlowSub (normal) | semmle.label | successor | -| cflow.cs:286:5:286:18 | enter ControlFlowSub | cflow.cs:286:34:286:34 | access to parameter i | semmle.label | successor | -| cflow.cs:286:5:286:18 | exit ControlFlowSub (normal) | cflow.cs:286:5:286:18 | exit ControlFlowSub | semmle.label | successor | -| cflow.cs:286:29:286:32 | call to constructor ControlFlowSub | cflow.cs:286:48:286:50 | {...} | semmle.label | successor | -| cflow.cs:286:34:286:34 | access to parameter i | cflow.cs:286:34:286:45 | call to method ToString | semmle.label | successor | -| cflow.cs:286:34:286:45 | call to method ToString | cflow.cs:286:29:286:32 | call to constructor ControlFlowSub | semmle.label | successor | -| cflow.cs:286:48:286:50 | {...} | cflow.cs:286:5:286:18 | exit ControlFlowSub (normal) | semmle.label | successor | -| cflow.cs:291:12:291:12 | enter M | cflow.cs:291:38:291:38 | access to parameter f | semmle.label | successor | -| cflow.cs:291:12:291:12 | exit M (normal) | cflow.cs:291:12:291:12 | exit M | semmle.label | successor | -| cflow.cs:291:38:291:38 | access to parameter f | cflow.cs:291:40:291:40 | 0 | semmle.label | successor | -| cflow.cs:291:38:291:41 | delegate call | cflow.cs:291:12:291:12 | exit M (normal) | semmle.label | successor | -| cflow.cs:291:40:291:40 | 0 | cflow.cs:291:38:291:41 | delegate call | semmle.label | successor | -| cflow.cs:296:5:296:25 | call to constructor Object | cflow.cs:296:52:296:54 | {...} | semmle.label | successor | -| cflow.cs:296:5:296:25 | enter NegationInConstructor | cflow.cs:296:5:296:25 | call to constructor Object | semmle.label | successor | -| cflow.cs:296:5:296:25 | exit NegationInConstructor (normal) | cflow.cs:296:5:296:25 | exit NegationInConstructor | semmle.label | successor | -| cflow.cs:296:52:296:54 | {...} | cflow.cs:296:5:296:25 | exit NegationInConstructor (normal) | semmle.label | successor | -| cflow.cs:298:10:298:10 | enter M | cflow.cs:299:5:301:5 | {...} | semmle.label | successor | -| cflow.cs:298:10:298:10 | exit M (normal) | cflow.cs:298:10:298:10 | exit M | semmle.label | successor | -| cflow.cs:299:5:301:5 | {...} | cflow.cs:300:9:300:73 | ...; | semmle.label | successor | -| cflow.cs:300:9:300:72 | object creation of type NegationInConstructor | cflow.cs:298:10:298:10 | exit M (normal) | semmle.label | successor | -| cflow.cs:300:9:300:73 | ...; | cflow.cs:300:38:300:38 | 0 | semmle.label | successor | -| cflow.cs:300:38:300:38 | 0 | cflow.cs:300:46:300:46 | access to parameter i | semmle.label | successor | -| cflow.cs:300:44:300:51 | [false] !... | cflow.cs:300:44:300:64 | ... && ... | semmle.label | false | -| cflow.cs:300:44:300:51 | [true] !... | cflow.cs:300:56:300:56 | access to parameter s | semmle.label | true | -| cflow.cs:300:44:300:64 | ... && ... | cflow.cs:300:70:300:71 | "" | semmle.label | successor | -| cflow.cs:300:46:300:46 | access to parameter i | cflow.cs:300:50:300:50 | 0 | semmle.label | successor | -| cflow.cs:300:46:300:50 | ... > ... | cflow.cs:300:44:300:51 | [false] !... | semmle.label | true | -| cflow.cs:300:46:300:50 | ... > ... | cflow.cs:300:44:300:51 | [true] !... | semmle.label | false | -| cflow.cs:300:50:300:50 | 0 | cflow.cs:300:46:300:50 | ... > ... | semmle.label | successor | -| cflow.cs:300:56:300:56 | access to parameter s | cflow.cs:300:61:300:64 | null | semmle.label | successor | -| cflow.cs:300:56:300:64 | ... != ... | cflow.cs:300:44:300:64 | ... && ... | semmle.label | successor | -| cflow.cs:300:61:300:64 | null | cflow.cs:300:56:300:64 | ... != ... | semmle.label | successor | -| cflow.cs:300:70:300:71 | "" | cflow.cs:300:9:300:72 | object creation of type NegationInConstructor | semmle.label | successor | +AccessorCalls.cs: +# 5| enter get_Item +#-----| -> access to parameter i + +# 5| exit get_Item + +# 5| exit get_Item (normal) +#-----| -> exit get_Item + +# 5| access to parameter i +#-----| -> exit get_Item (normal) + +# 5| enter set_Item +#-----| -> {...} + +# 5| exit set_Item + +# 5| exit set_Item (normal) +#-----| -> exit set_Item + +# 5| {...} +#-----| -> exit set_Item (normal) + +# 7| enter add_Event +#-----| -> {...} + +# 7| exit add_Event + +# 7| exit add_Event (normal) +#-----| -> exit add_Event + +# 7| {...} +#-----| -> exit add_Event (normal) + +# 7| enter remove_Event +#-----| -> {...} + +# 7| exit remove_Event + +# 7| exit remove_Event (normal) +#-----| -> exit remove_Event + +# 7| {...} +#-----| -> exit remove_Event (normal) + +# 10| enter M1 +#-----| -> {...} + +# 10| exit M1 + +# 10| exit M1 (normal) +#-----| -> exit M1 + +# 11| {...} +#-----| -> ...; + +# 12| ...; +#-----| -> this access + +# 12| ... = ... +#-----| -> ...; + +# 12| this access +#-----| -> this access + +# 12| access to field Field +#-----| -> ... = ... + +# 12| this access +#-----| -> access to field Field + +# 13| ...; +#-----| -> this access + +# 13| ... = ... +#-----| -> ...; + +# 13| access to property Prop +#-----| -> ... = ... + +# 13| this access +#-----| -> this access + +# 13| access to property Prop +#-----| -> access to property Prop + +# 13| this access +#-----| -> access to property Prop + +# 14| ...; +#-----| -> this access + +# 14| ... = ... +#-----| -> ...; + +# 14| access to indexer +#-----| -> ... = ... + +# 14| this access +#-----| -> 0 + +# 14| 0 +#-----| -> this access + +# 14| access to indexer +#-----| -> access to indexer + +# 14| this access +#-----| -> 1 + +# 14| 1 +#-----| -> access to indexer + +# 15| ...; +#-----| -> this access + +# 15| ... += ... +#-----| -> ...; + +# 15| access to event Event +#-----| -> ... += ... + +# 15| this access +#-----| -> access to parameter e + +# 15| access to parameter e +#-----| -> access to event Event + +# 16| ...; +#-----| -> this access + +# 16| ... -= ... +#-----| -> exit M1 (normal) + +# 16| access to event Event +#-----| -> ... -= ... + +# 16| this access +#-----| -> access to parameter e + +# 16| access to parameter e +#-----| -> access to event Event + +# 19| enter M2 +#-----| -> {...} + +# 19| exit M2 + +# 19| exit M2 (normal) +#-----| -> exit M2 + +# 20| {...} +#-----| -> ...; + +# 21| ...; +#-----| -> this access + +# 21| ... = ... +#-----| -> ...; + +# 21| access to field x +#-----| -> this access + +# 21| this access +#-----| -> access to field x + +# 21| access to field Field +#-----| -> ... = ... + +# 21| access to field x +#-----| -> access to field Field + +# 21| this access +#-----| -> access to field x + +# 22| ...; +#-----| -> this access + +# 22| ... = ... +#-----| -> ...; + +# 22| access to property Prop +#-----| -> ... = ... + +# 22| access to field x +#-----| -> this access + +# 22| this access +#-----| -> access to field x + +# 22| access to property Prop +#-----| -> access to property Prop + +# 22| access to field x +#-----| -> access to property Prop + +# 22| this access +#-----| -> access to field x + +# 23| ...; +#-----| -> this access + +# 23| ... = ... +#-----| -> ...; + +# 23| access to indexer +#-----| -> ... = ... + +# 23| access to field x +#-----| -> 0 + +# 23| this access +#-----| -> access to field x + +# 23| 0 +#-----| -> this access + +# 23| access to indexer +#-----| -> access to indexer + +# 23| access to field x +#-----| -> 1 + +# 23| this access +#-----| -> access to field x + +# 23| 1 +#-----| -> access to indexer + +# 24| ...; +#-----| -> this access + +# 24| ... += ... +#-----| -> ...; + +# 24| access to event Event +#-----| -> ... += ... + +# 24| access to field x +#-----| -> access to parameter e + +# 24| this access +#-----| -> access to field x + +# 24| access to parameter e +#-----| -> access to event Event + +# 25| ...; +#-----| -> this access + +# 25| ... -= ... +#-----| -> exit M2 (normal) + +# 25| access to event Event +#-----| -> ... -= ... + +# 25| access to field x +#-----| -> access to parameter e + +# 25| this access +#-----| -> access to field x + +# 25| access to parameter e +#-----| -> access to event Event + +# 28| enter M3 +#-----| -> {...} + +# 28| exit M3 + +# 28| exit M3 (normal) +#-----| -> exit M3 + +# 29| {...} +#-----| -> ...; + +# 30| ...; +#-----| -> this access + +# 30| ...++ +#-----| -> ...; + +# 30| access to field Field +#-----| -> ...++ + +# 30| this access +#-----| -> access to field Field + +# 31| ...; +#-----| -> this access + +# 31| ...++ +#-----| -> ...; + +# 31| access to property Prop +#-----| -> ...++ + +# 31| this access +#-----| -> access to property Prop + +# 32| ...; +#-----| -> this access + +# 32| ...++ +#-----| -> exit M3 (normal) + +# 32| access to indexer +#-----| -> ...++ + +# 32| this access +#-----| -> 0 + +# 32| 0 +#-----| -> access to indexer + +# 35| enter M4 +#-----| -> {...} + +# 35| exit M4 + +# 35| exit M4 (normal) +#-----| -> exit M4 + +# 36| {...} +#-----| -> ...; + +# 37| ...; +#-----| -> this access + +# 37| ...++ +#-----| -> ...; + +# 37| access to field Field +#-----| -> ...++ + +# 37| access to field x +#-----| -> access to field Field + +# 37| this access +#-----| -> access to field x + +# 38| ...; +#-----| -> this access + +# 38| ...++ +#-----| -> ...; + +# 38| access to property Prop +#-----| -> ...++ + +# 38| access to field x +#-----| -> access to property Prop + +# 38| this access +#-----| -> access to field x + +# 39| ...; +#-----| -> this access + +# 39| ...++ +#-----| -> exit M4 (normal) + +# 39| access to indexer +#-----| -> ...++ + +# 39| access to field x +#-----| -> 0 + +# 39| this access +#-----| -> access to field x + +# 39| 0 +#-----| -> access to indexer + +# 42| enter M5 +#-----| -> {...} + +# 42| exit M5 + +# 42| exit M5 (normal) +#-----| -> exit M5 + +# 43| {...} +#-----| -> ...; + +# 44| ...; +#-----| -> this access + +# 44| ... = ... +#-----| -> ...; + +# 44| this access +#-----| -> this access + +# 44| ... + ... +#-----| -> ... = ... + +# 44| access to field Field +#-----| -> this access + +# 44| this access +#-----| -> access to field Field + +# 44| access to field Field +#-----| -> ... + ... + +# 44| this access +#-----| -> access to field Field + +# 45| ...; +#-----| -> this access + +# 45| ... = ... +#-----| -> ...; + +# 45| access to property Prop +#-----| -> ... = ... + +# 45| this access +#-----| -> this access + +# 45| ... + ... +#-----| -> access to property Prop + +# 45| access to property Prop +#-----| -> this access + +# 45| this access +#-----| -> access to property Prop + +# 45| access to property Prop +#-----| -> ... + ... + +# 45| this access +#-----| -> access to property Prop + +# 46| ...; +#-----| -> this access + +# 46| ... = ... +#-----| -> exit M5 (normal) + +# 46| access to indexer +#-----| -> ... = ... + +# 46| this access +#-----| -> 0 + +# 46| ... + ... +#-----| -> access to indexer + +# 46| access to indexer +#-----| -> this access + +# 46| this access +#-----| -> 0 + +# 46| 0 +#-----| -> this access + +# 46| 0 +#-----| -> access to indexer + +# 46| access to indexer +#-----| -> ... + ... + +# 46| this access +#-----| -> 0 + +# 46| 0 +#-----| -> access to indexer + +# 49| enter M6 +#-----| -> {...} + +# 49| exit M6 + +# 49| exit M6 (normal) +#-----| -> exit M6 + +# 50| {...} +#-----| -> ...; + +# 51| ...; +#-----| -> this access + +# 51| ... = ... +#-----| -> ...; + +# 51| access to field x +#-----| -> this access + +# 51| this access +#-----| -> access to field x + +# 51| ... + ... +#-----| -> ... = ... + +# 51| access to field Field +#-----| -> this access + +# 51| access to field x +#-----| -> access to field Field + +# 51| this access +#-----| -> access to field x + +# 51| access to field Field +#-----| -> ... + ... + +# 51| access to field x +#-----| -> access to field Field + +# 51| this access +#-----| -> access to field x + +# 52| ...; +#-----| -> this access + +# 52| ... = ... +#-----| -> ...; + +# 52| access to property Prop +#-----| -> ... = ... + +# 52| access to field x +#-----| -> this access + +# 52| this access +#-----| -> access to field x + +# 52| ... + ... +#-----| -> access to property Prop + +# 52| access to property Prop +#-----| -> this access + +# 52| access to field x +#-----| -> access to property Prop + +# 52| this access +#-----| -> access to field x + +# 52| access to property Prop +#-----| -> ... + ... + +# 52| access to field x +#-----| -> access to property Prop + +# 52| this access +#-----| -> access to field x + +# 53| ...; +#-----| -> this access + +# 53| ... = ... +#-----| -> exit M6 (normal) + +# 53| access to indexer +#-----| -> ... = ... + +# 53| access to field x +#-----| -> 0 + +# 53| this access +#-----| -> access to field x + +# 53| ... + ... +#-----| -> access to indexer + +# 53| access to indexer +#-----| -> this access + +# 53| access to field x +#-----| -> 0 + +# 53| this access +#-----| -> access to field x + +# 53| 0 +#-----| -> this access + +# 53| 0 +#-----| -> access to indexer + +# 53| access to indexer +#-----| -> ... + ... + +# 53| access to field x +#-----| -> 0 + +# 53| this access +#-----| -> access to field x + +# 53| 0 +#-----| -> access to indexer + +# 56| enter M7 +#-----| -> {...} + +# 56| exit M7 + +# 56| exit M7 (normal) +#-----| -> exit M7 + +# 57| {...} +#-----| -> ...; + +# 58| ...; +#-----| -> this access + +# 58| ... = ... +#-----| -> exit M7 (normal) + +# 58| (..., ...) +#-----| -> this access + +# 58| this access +#-----| -> this access + +# 58| access to property Prop +#-----| -> access to indexer + +# 58| this access +#-----| -> this access + +# 58| (..., ...) +#-----| -> (..., ...) + +# 58| access to indexer +#-----| -> ... = ... + +# 58| this access +#-----| -> 0 + +# 58| 0 +#-----| -> (..., ...) + +# 58| (..., ...) +#-----| -> access to property Prop + +# 58| access to field Field +#-----| -> this access + +# 58| this access +#-----| -> access to field Field + +# 58| access to property Prop +#-----| -> 0 + +# 58| this access +#-----| -> access to property Prop + +# 58| (..., ...) +#-----| -> (..., ...) + +# 58| 0 +#-----| -> this access + +# 58| access to indexer +#-----| -> (..., ...) + +# 58| this access +#-----| -> 1 + +# 58| 1 +#-----| -> access to indexer + +# 61| enter M8 +#-----| -> {...} + +# 61| exit M8 + +# 61| exit M8 (normal) +#-----| -> exit M8 + +# 62| {...} +#-----| -> ...; + +# 63| ...; +#-----| -> this access + +# 63| ... = ... +#-----| -> exit M8 (normal) + +# 63| (..., ...) +#-----| -> this access + +# 63| access to field x +#-----| -> this access + +# 63| this access +#-----| -> access to field x + +# 63| access to property Prop +#-----| -> access to indexer + +# 63| access to field x +#-----| -> this access + +# 63| this access +#-----| -> access to field x + +# 63| (..., ...) +#-----| -> (..., ...) + +# 63| access to indexer +#-----| -> ... = ... + +# 63| access to field x +#-----| -> 0 + +# 63| this access +#-----| -> access to field x + +# 63| 0 +#-----| -> (..., ...) + +# 63| (..., ...) +#-----| -> access to property Prop + +# 63| access to field Field +#-----| -> this access + +# 63| access to field x +#-----| -> access to field Field + +# 63| this access +#-----| -> access to field x + +# 63| access to property Prop +#-----| -> 0 + +# 63| access to field x +#-----| -> access to property Prop + +# 63| this access +#-----| -> access to field x + +# 63| (..., ...) +#-----| -> (..., ...) + +# 63| 0 +#-----| -> this access + +# 63| access to indexer +#-----| -> (..., ...) + +# 63| access to field x +#-----| -> 1 + +# 63| this access +#-----| -> access to field x + +# 63| 1 +#-----| -> access to indexer + +# 66| enter M9 +#-----| -> {...} + +# 66| exit M9 + +# 66| exit M9 (normal) +#-----| -> exit M9 + +# 67| {...} +#-----| -> ... ...; + +# 68| ... ...; +#-----| -> access to parameter o + +# 68| dynamic d = ... +#-----| -> ...; + +# 68| access to parameter o +#-----| -> dynamic d = ... + +# 69| ...; +#-----| -> access to local variable d + +# 69| ... = ... +#-----| -> ...; + +# 69| dynamic access to member MaybeProp1 +#-----| -> ... = ... + +# 69| access to local variable d +#-----| -> access to local variable d + +# 69| dynamic access to member MaybeProp2 +#-----| -> dynamic access to member MaybeProp1 + +# 69| access to local variable d +#-----| -> dynamic access to member MaybeProp2 + +# 70| ...; +#-----| -> access to local variable d + +# 70| dynamic call to operator ++ +#-----| -> ...; + +# 70| dynamic access to member MaybeProp +#-----| -> dynamic call to operator ++ + +# 70| access to local variable d +#-----| -> dynamic access to member MaybeProp + +# 71| ...; +#-----| -> access to local variable d + +# 71| ... = ... +#-----| -> ...; + +# 71| dynamic access to member MaybeEvent +#-----| -> ... = ... + +# 71| access to local variable d +#-----| -> access to local variable d + +# 71| dynamic call to operator + +#-----| -> dynamic access to member MaybeEvent + +# 71| dynamic access to member MaybeEvent +#-----| -> access to parameter e + +# 71| access to local variable d +#-----| -> dynamic access to member MaybeEvent + +# 71| access to parameter e +#-----| -> dynamic call to operator + + +# 72| ...; +#-----| -> access to local variable d + +# 72| ... = ... +#-----| -> ...; + +# 72| dynamic access to element +#-----| -> ... = ... + +# 72| access to local variable d +#-----| -> 0 + +# 72| dynamic call to operator + +#-----| -> dynamic access to element + +# 72| dynamic access to element +#-----| -> access to local variable d + +# 72| access to local variable d +#-----| -> 0 + +# 72| 0 +#-----| -> access to local variable d + +# 72| 0 +#-----| -> dynamic access to element + +# 72| dynamic access to element +#-----| -> dynamic call to operator + + +# 72| access to local variable d +#-----| -> 1 + +# 72| 1 +#-----| -> dynamic access to element + +# 73| ...; +#-----| -> access to local variable d + +# 73| ... = ... +#-----| -> exit M9 (normal) + +# 73| (..., ...) +#-----| -> access to local variable d + +# 73| dynamic access to member MaybeProp1 +#-----| -> access to property Prop + +# 73| access to local variable d +#-----| -> this access + +# 73| access to property Prop +#-----| -> dynamic access to element + +# 73| this access +#-----| -> access to local variable d + +# 73| (..., ...) +#-----| -> (..., ...) + +# 73| dynamic access to element +#-----| -> ... = ... + +# 73| access to local variable d +#-----| -> 0 + +# 73| 0 +#-----| -> (..., ...) + +# 73| (..., ...) +#-----| -> dynamic access to member MaybeProp1 + +# 73| dynamic access to member MaybeProp1 +#-----| -> this access + +# 73| access to local variable d +#-----| -> dynamic access to member MaybeProp1 + +# 73| access to property Prop +#-----| -> 0 + +# 73| this access +#-----| -> access to property Prop + +# 73| (..., ...) +#-----| -> (..., ...) + +# 73| 0 +#-----| -> access to local variable d + +# 73| dynamic access to element +#-----| -> (..., ...) + +# 73| access to local variable d +#-----| -> 1 + +# 73| 1 +#-----| -> dynamic access to element + +ArrayCreation.cs: +# 3| enter M1 +#-----| -> 0 + +# 3| exit M1 + +# 3| exit M1 (normal) +#-----| -> exit M1 + +# 3| array creation of type Int32[] +#-----| -> exit M1 (normal) + +# 3| 0 +#-----| -> array creation of type Int32[] + +# 5| enter M2 +#-----| -> 0 + +# 5| exit M2 + +# 5| exit M2 (normal) +#-----| -> exit M2 + +# 5| array creation of type Int32[,] +#-----| -> exit M2 (normal) + +# 5| 0 +#-----| -> 1 + +# 5| 1 +#-----| -> array creation of type Int32[,] + +# 7| enter M3 +#-----| -> 2 + +# 7| exit M3 + +# 7| exit M3 (normal) +#-----| -> exit M3 + +# 7| array creation of type Int32[] +#-----| -> 0 + +# 7| 2 +#-----| -> array creation of type Int32[] + +# 7| { ..., ... } +#-----| -> exit M3 (normal) + +# 7| 0 +#-----| -> 1 + +# 7| 1 +#-----| -> { ..., ... } + +# 9| enter M4 +#-----| -> 2 + +# 9| exit M4 + +# 9| exit M4 (normal) +#-----| -> exit M4 + +# 9| array creation of type Int32[,] +#-----| -> 0 + +# 9| 2 +#-----| -> 2 + +# 9| 2 +#-----| -> array creation of type Int32[,] + +# 9| { ..., ... } +#-----| -> exit M4 (normal) + +# 9| { ..., ... } +#-----| -> 2 + +# 9| 0 +#-----| -> 1 + +# 9| 1 +#-----| -> { ..., ... } + +# 9| { ..., ... } +#-----| -> { ..., ... } + +# 9| 2 +#-----| -> 3 + +# 9| 3 +#-----| -> { ..., ... } + +Assert.cs: +# 7| enter M1 +#-----| -> {...} + +# 7| exit M1 + +# 7| exit M1 (abnormal) +#-----| -> exit M1 + +# 7| exit M1 (normal) +#-----| -> exit M1 + +# 8| {...} +#-----| -> ... ...; + +# 9| ... ...; +#-----| -> access to parameter b + +# 9| String s = ... +#-----| -> ...; + +# 9| ... ? ... : ... +#-----| -> String s = ... + +# 9| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 9| null +#-----| -> ... ? ... : ... + +# 9| "" +#-----| -> ... ? ... : ... + +# 10| ...; +#-----| -> access to local variable s + +# 10| [assertion failure] call to method Assert +#-----| exit -> exit M1 (abnormal) + +# 10| [assertion success] call to method Assert +#-----| -> ...; + +# 10| ... != ... +#-----| false -> [assertion failure] call to method Assert +#-----| true -> [assertion success] call to method Assert + +# 10| access to local variable s +#-----| -> null + +# 10| null +#-----| -> ... != ... + +# 11| ...; +#-----| -> access to local variable s + +# 11| call to method WriteLine +#-----| -> exit M1 (normal) + +# 11| access to property Length +#-----| -> call to method WriteLine + +# 11| access to local variable s +#-----| -> access to property Length + +# 14| enter M2 +#-----| -> {...} + +# 14| exit M2 + +# 14| exit M2 (abnormal) +#-----| -> exit M2 + +# 14| exit M2 (normal) +#-----| -> exit M2 + +# 15| {...} +#-----| -> ... ...; + +# 16| ... ...; +#-----| -> access to parameter b + +# 16| String s = ... +#-----| -> ...; + +# 16| ... ? ... : ... +#-----| -> String s = ... + +# 16| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 16| null +#-----| -> ... ? ... : ... + +# 16| "" +#-----| -> ... ? ... : ... + +# 17| ...; +#-----| -> access to local variable s + +# 17| [assertion failure] call to method IsNull +#-----| exception(AssertFailedException) -> exit M2 (abnormal) + +# 17| [assertion success] call to method IsNull +#-----| -> ...; + +# 17| access to local variable s +#-----| non-null -> [assertion failure] call to method IsNull +#-----| null -> [assertion success] call to method IsNull + +# 18| ...; +#-----| -> access to local variable s + +# 18| call to method WriteLine +#-----| -> exit M2 (normal) + +# 18| access to property Length +#-----| -> call to method WriteLine + +# 18| access to local variable s +#-----| -> access to property Length + +# 21| enter M3 +#-----| -> {...} + +# 21| exit M3 + +# 21| exit M3 (abnormal) +#-----| -> exit M3 + +# 21| exit M3 (normal) +#-----| -> exit M3 + +# 22| {...} +#-----| -> ... ...; + +# 23| ... ...; +#-----| -> access to parameter b + +# 23| String s = ... +#-----| -> ...; + +# 23| ... ? ... : ... +#-----| -> String s = ... + +# 23| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 23| null +#-----| -> ... ? ... : ... + +# 23| "" +#-----| -> ... ? ... : ... + +# 24| ...; +#-----| -> access to local variable s + +# 24| [assertion failure] call to method IsNotNull +#-----| exception(AssertFailedException) -> exit M3 (abnormal) + +# 24| [assertion success] call to method IsNotNull +#-----| -> ...; + +# 24| access to local variable s +#-----| null -> [assertion failure] call to method IsNotNull +#-----| non-null -> [assertion success] call to method IsNotNull + +# 25| ...; +#-----| -> access to local variable s + +# 25| call to method WriteLine +#-----| -> exit M3 (normal) + +# 25| access to property Length +#-----| -> call to method WriteLine + +# 25| access to local variable s +#-----| -> access to property Length + +# 28| enter M4 +#-----| -> {...} + +# 28| exit M4 + +# 28| exit M4 (abnormal) +#-----| -> exit M4 + +# 28| exit M4 (normal) +#-----| -> exit M4 + +# 29| {...} +#-----| -> ... ...; + +# 30| ... ...; +#-----| -> access to parameter b + +# 30| String s = ... +#-----| -> ...; + +# 30| ... ? ... : ... +#-----| -> String s = ... + +# 30| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 30| null +#-----| -> ... ? ... : ... + +# 30| "" +#-----| -> ... ? ... : ... + +# 31| ...; +#-----| -> access to local variable s + +# 31| [assertion failure] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M4 (abnormal) + +# 31| [assertion success] call to method IsTrue +#-----| -> ...; + +# 31| ... == ... +#-----| false -> [assertion failure] call to method IsTrue +#-----| true -> [assertion success] call to method IsTrue + +# 31| access to local variable s +#-----| -> null + +# 31| null +#-----| -> ... == ... + +# 32| ...; +#-----| -> access to local variable s + +# 32| call to method WriteLine +#-----| -> exit M4 (normal) + +# 32| access to property Length +#-----| -> call to method WriteLine + +# 32| access to local variable s +#-----| -> access to property Length + +# 35| enter M5 +#-----| -> {...} + +# 35| exit M5 + +# 35| exit M5 (abnormal) +#-----| -> exit M5 + +# 35| exit M5 (normal) +#-----| -> exit M5 + +# 36| {...} +#-----| -> ... ...; + +# 37| ... ...; +#-----| -> access to parameter b + +# 37| String s = ... +#-----| -> ...; + +# 37| ... ? ... : ... +#-----| -> String s = ... + +# 37| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 37| null +#-----| -> ... ? ... : ... + +# 37| "" +#-----| -> ... ? ... : ... + +# 38| ...; +#-----| -> access to local variable s + +# 38| [assertion failure] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M5 (abnormal) + +# 38| [assertion success] call to method IsTrue +#-----| -> ...; + +# 38| ... != ... +#-----| false -> [assertion failure] call to method IsTrue +#-----| true -> [assertion success] call to method IsTrue + +# 38| access to local variable s +#-----| -> null + +# 38| null +#-----| -> ... != ... + +# 39| ...; +#-----| -> access to local variable s + +# 39| call to method WriteLine +#-----| -> exit M5 (normal) + +# 39| access to property Length +#-----| -> call to method WriteLine + +# 39| access to local variable s +#-----| -> access to property Length + +# 42| enter M6 +#-----| -> {...} + +# 42| exit M6 + +# 42| exit M6 (abnormal) +#-----| -> exit M6 + +# 42| exit M6 (normal) +#-----| -> exit M6 + +# 43| {...} +#-----| -> ... ...; + +# 44| ... ...; +#-----| -> access to parameter b + +# 44| String s = ... +#-----| -> ...; + +# 44| ... ? ... : ... +#-----| -> String s = ... + +# 44| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 44| null +#-----| -> ... ? ... : ... + +# 44| "" +#-----| -> ... ? ... : ... + +# 45| ...; +#-----| -> access to local variable s + +# 45| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M6 (abnormal) + +# 45| [assertion success] call to method IsFalse +#-----| -> ...; + +# 45| ... != ... +#-----| true -> [assertion failure] call to method IsFalse +#-----| false -> [assertion success] call to method IsFalse + +# 45| access to local variable s +#-----| -> null + +# 45| null +#-----| -> ... != ... + +# 46| ...; +#-----| -> access to local variable s + +# 46| call to method WriteLine +#-----| -> exit M6 (normal) + +# 46| access to property Length +#-----| -> call to method WriteLine + +# 46| access to local variable s +#-----| -> access to property Length + +# 49| enter M7 +#-----| -> {...} + +# 49| exit M7 + +# 49| exit M7 (abnormal) +#-----| -> exit M7 + +# 49| exit M7 (normal) +#-----| -> exit M7 + +# 50| {...} +#-----| -> ... ...; + +# 51| ... ...; +#-----| -> access to parameter b + +# 51| String s = ... +#-----| -> ...; + +# 51| ... ? ... : ... +#-----| -> String s = ... + +# 51| access to parameter b +#-----| true -> null +#-----| false -> "" + +# 51| null +#-----| -> ... ? ... : ... + +# 51| "" +#-----| -> ... ? ... : ... + +# 52| ...; +#-----| -> access to local variable s + +# 52| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M7 (abnormal) + +# 52| [assertion success] call to method IsFalse +#-----| -> ...; + +# 52| ... == ... +#-----| true -> [assertion failure] call to method IsFalse +#-----| false -> [assertion success] call to method IsFalse + +# 52| access to local variable s +#-----| -> null + +# 52| null +#-----| -> ... == ... + +# 53| ...; +#-----| -> access to local variable s + +# 53| call to method WriteLine +#-----| -> exit M7 (normal) + +# 53| access to property Length +#-----| -> call to method WriteLine + +# 53| access to local variable s +#-----| -> access to property Length + +# 56| enter M8 +#-----| -> {...} + +# 56| exit M8 + +# 56| exit M8 (abnormal) +#-----| -> exit M8 + +# 56| exit M8 (normal) +#-----| -> exit M8 + +# 57| {...} +#-----| -> ... ...; + +# 58| ... ...; +#-----| -> access to parameter b + +# 58| [b (line 56): false] String s = ... +#-----| -> [b (line 56): false] ...; + +# 58| [b (line 56): true] String s = ... +#-----| -> [b (line 56): true] ...; + +# 58| [b (line 56): false] ... ? ... : ... +#-----| -> [b (line 56): false] String s = ... + +# 58| [b (line 56): true] ... ? ... : ... +#-----| -> [b (line 56): true] String s = ... + +# 58| access to parameter b +#-----| true -> [b (line 56): true] null +#-----| false -> [b (line 56): false] "" + +# 58| [b (line 56): true] null +#-----| -> [b (line 56): true] ... ? ... : ... + +# 58| [b (line 56): false] "" +#-----| -> [b (line 56): false] ... ? ... : ... + +# 59| [b (line 56): false] ...; +#-----| -> [b (line 56): false] access to local variable s + +# 59| [b (line 56): true] ...; +#-----| -> [b (line 56): true] access to local variable s + +# 59| [assertion failure] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M8 (abnormal) + +# 59| [assertion success] call to method IsTrue +#-----| -> ...; + +# 59| [false] ... && ... +#-----| false -> [assertion failure] call to method IsTrue + +# 59| [true] ... && ... +#-----| true -> [assertion success] call to method IsTrue + +# 59| [b (line 56): false] ... != ... +#-----| false -> [false] ... && ... +#-----| true -> [b (line 56): false] access to parameter b + +# 59| [b (line 56): true] ... != ... +#-----| false -> [false] ... && ... +#-----| true -> [b (line 56): true] access to parameter b + +# 59| [b (line 56): false] access to local variable s +#-----| -> [b (line 56): false] null + +# 59| [b (line 56): true] access to local variable s +#-----| -> [b (line 56): true] null + +# 59| [b (line 56): false] null +#-----| -> [b (line 56): false] ... != ... + +# 59| [b (line 56): true] null +#-----| -> [b (line 56): true] ... != ... + +# 59| [b (line 56): false] access to parameter b +#-----| false -> [false] ... && ... + +# 59| [b (line 56): true] access to parameter b +#-----| true -> [true] ... && ... + +# 60| ...; +#-----| -> access to local variable s + +# 60| call to method WriteLine +#-----| -> exit M8 (normal) + +# 60| access to property Length +#-----| -> call to method WriteLine + +# 60| access to local variable s +#-----| -> access to property Length + +# 63| enter M9 +#-----| -> {...} + +# 63| exit M9 + +# 63| exit M9 (abnormal) +#-----| -> exit M9 + +# 63| exit M9 (normal) +#-----| -> exit M9 + +# 64| {...} +#-----| -> ... ...; + +# 65| ... ...; +#-----| -> access to parameter b + +# 65| [b (line 63): false] String s = ... +#-----| -> [b (line 63): false] ...; + +# 65| [b (line 63): true] String s = ... +#-----| -> [b (line 63): true] ...; + +# 65| [b (line 63): false] ... ? ... : ... +#-----| -> [b (line 63): false] String s = ... + +# 65| [b (line 63): true] ... ? ... : ... +#-----| -> [b (line 63): true] String s = ... + +# 65| access to parameter b +#-----| true -> [b (line 63): true] null +#-----| false -> [b (line 63): false] "" + +# 65| [b (line 63): true] null +#-----| -> [b (line 63): true] ... ? ... : ... + +# 65| [b (line 63): false] "" +#-----| -> [b (line 63): false] ... ? ... : ... + +# 66| [b (line 63): false] ...; +#-----| -> [b (line 63): false] access to local variable s + +# 66| [b (line 63): true] ...; +#-----| -> [b (line 63): true] access to local variable s + +# 66| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M9 (abnormal) + +# 66| [assertion success] call to method IsFalse +#-----| -> ...; + +# 66| [false] ... || ... +#-----| false -> [assertion success] call to method IsFalse + +# 66| [true] ... || ... +#-----| true -> [assertion failure] call to method IsFalse + +# 66| [b (line 63): false] ... == ... +#-----| true -> [true] ... || ... +#-----| false -> [b (line 63): false] access to parameter b + +# 66| [b (line 63): true] ... == ... +#-----| true -> [true] ... || ... +#-----| false -> [b (line 63): true] access to parameter b + +# 66| [b (line 63): false] access to local variable s +#-----| -> [b (line 63): false] null + +# 66| [b (line 63): true] access to local variable s +#-----| -> [b (line 63): true] null + +# 66| [b (line 63): false] null +#-----| -> [b (line 63): false] ... == ... + +# 66| [b (line 63): true] null +#-----| -> [b (line 63): true] ... == ... + +# 66| [b (line 63): false] access to parameter b +#-----| false -> [false] ... || ... + +# 66| [b (line 63): true] access to parameter b +#-----| true -> [true] ... || ... + +# 67| ...; +#-----| -> access to local variable s + +# 67| call to method WriteLine +#-----| -> exit M9 (normal) + +# 67| access to property Length +#-----| -> call to method WriteLine + +# 67| access to local variable s +#-----| -> access to property Length + +# 70| enter M10 +#-----| -> {...} + +# 70| exit M10 + +# 70| exit M10 (abnormal) +#-----| -> exit M10 + +# 70| exit M10 (normal) +#-----| -> exit M10 + +# 71| {...} +#-----| -> ... ...; + +# 72| ... ...; +#-----| -> access to parameter b + +# 72| [b (line 70): false] String s = ... +#-----| -> [b (line 70): false] ...; + +# 72| [b (line 70): true] String s = ... +#-----| -> [b (line 70): true] ...; + +# 72| [b (line 70): false] ... ? ... : ... +#-----| -> [b (line 70): false] String s = ... + +# 72| [b (line 70): true] ... ? ... : ... +#-----| -> [b (line 70): true] String s = ... + +# 72| access to parameter b +#-----| true -> [b (line 70): true] null +#-----| false -> [b (line 70): false] "" + +# 72| [b (line 70): true] null +#-----| -> [b (line 70): true] ... ? ... : ... + +# 72| [b (line 70): false] "" +#-----| -> [b (line 70): false] ... ? ... : ... + +# 73| [b (line 70): false] ...; +#-----| -> [b (line 70): false] access to local variable s + +# 73| [b (line 70): true] ...; +#-----| -> [b (line 70): true] access to local variable s + +# 73| [assertion failure] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M10 (abnormal) + +# 73| [assertion success] call to method IsTrue +#-----| -> ...; + +# 73| [false] ... && ... +#-----| false -> [assertion failure] call to method IsTrue + +# 73| [true] ... && ... +#-----| true -> [assertion success] call to method IsTrue + +# 73| [b (line 70): false] ... == ... +#-----| false -> [false] ... && ... +#-----| true -> [b (line 70): false] access to parameter b + +# 73| [b (line 70): true] ... == ... +#-----| false -> [false] ... && ... +#-----| true -> [b (line 70): true] access to parameter b + +# 73| [b (line 70): false] access to local variable s +#-----| -> [b (line 70): false] null + +# 73| [b (line 70): true] access to local variable s +#-----| -> [b (line 70): true] null + +# 73| [b (line 70): false] null +#-----| -> [b (line 70): false] ... == ... + +# 73| [b (line 70): true] null +#-----| -> [b (line 70): true] ... == ... + +# 73| [b (line 70): false] access to parameter b +#-----| false -> [false] ... && ... + +# 73| [b (line 70): true] access to parameter b +#-----| true -> [true] ... && ... + +# 74| ...; +#-----| -> access to local variable s + +# 74| call to method WriteLine +#-----| -> exit M10 (normal) + +# 74| access to property Length +#-----| -> call to method WriteLine + +# 74| access to local variable s +#-----| -> access to property Length + +# 77| enter M11 +#-----| -> {...} + +# 77| exit M11 + +# 77| exit M11 (abnormal) +#-----| -> exit M11 + +# 77| exit M11 (normal) +#-----| -> exit M11 + +# 78| {...} +#-----| -> ... ...; + +# 79| ... ...; +#-----| -> access to parameter b + +# 79| [b (line 77): false] String s = ... +#-----| -> [b (line 77): false] ...; + +# 79| [b (line 77): true] String s = ... +#-----| -> [b (line 77): true] ...; + +# 79| [b (line 77): false] ... ? ... : ... +#-----| -> [b (line 77): false] String s = ... + +# 79| [b (line 77): true] ... ? ... : ... +#-----| -> [b (line 77): true] String s = ... + +# 79| access to parameter b +#-----| true -> [b (line 77): true] null +#-----| false -> [b (line 77): false] "" + +# 79| [b (line 77): true] null +#-----| -> [b (line 77): true] ... ? ... : ... + +# 79| [b (line 77): false] "" +#-----| -> [b (line 77): false] ... ? ... : ... + +# 80| [b (line 77): false] ...; +#-----| -> [b (line 77): false] access to local variable s + +# 80| [b (line 77): true] ...; +#-----| -> [b (line 77): true] access to local variable s + +# 80| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M11 (abnormal) + +# 80| [assertion success] call to method IsFalse +#-----| -> ...; + +# 80| [false] ... || ... +#-----| false -> [assertion success] call to method IsFalse + +# 80| [true] ... || ... +#-----| true -> [assertion failure] call to method IsFalse + +# 80| [b (line 77): false] ... != ... +#-----| true -> [true] ... || ... +#-----| false -> [b (line 77): false] access to parameter b + +# 80| [b (line 77): true] ... != ... +#-----| true -> [true] ... || ... +#-----| false -> [b (line 77): true] access to parameter b + +# 80| [b (line 77): false] access to local variable s +#-----| -> [b (line 77): false] null + +# 80| [b (line 77): true] access to local variable s +#-----| -> [b (line 77): true] null + +# 80| [b (line 77): false] null +#-----| -> [b (line 77): false] ... != ... + +# 80| [b (line 77): true] null +#-----| -> [b (line 77): true] ... != ... + +# 80| [b (line 77): false] access to parameter b +#-----| false -> [false] ... || ... + +# 80| [b (line 77): true] access to parameter b +#-----| true -> [true] ... || ... + +# 81| ...; +#-----| -> access to local variable s + +# 81| call to method WriteLine +#-----| -> exit M11 (normal) + +# 81| access to property Length +#-----| -> call to method WriteLine + +# 81| access to local variable s +#-----| -> access to property Length + +# 84| enter M12 +#-----| -> {...} + +# 84| exit M12 + +# 84| exit M12 (abnormal) +#-----| -> exit M12 + +# 84| exit M12 (normal) +#-----| -> exit M12 + +# 85| {...} +#-----| -> ... ...; + +# 86| ... ...; +#-----| -> access to parameter b + +# 86| [b (line 84): false] String s = ... +#-----| -> [b (line 84): false] ...; + +# 86| [b (line 84): true] String s = ... +#-----| -> [b (line 84): true] ...; + +# 86| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] String s = ... + +# 86| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] String s = ... + +# 86| access to parameter b +#-----| true -> [b (line 84): true] null +#-----| false -> [b (line 84): false] "" + +# 86| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 86| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 87| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 87| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 87| [assertion failure, b (line 84): false] call to method Assert +#-----| exit -> exit M12 (abnormal) + +# 87| [assertion failure, b (line 84): true] call to method Assert +#-----| exit -> exit M12 (abnormal) + +# 87| [assertion success, b (line 84): false] call to method Assert +#-----| -> [b (line 84): false] ...; + +# 87| [assertion success, b (line 84): true] call to method Assert +#-----| -> [b (line 84): true] ...; + +# 87| [b (line 84): false] ... != ... +#-----| false -> [assertion failure, b (line 84): false] call to method Assert +#-----| true -> [assertion success, b (line 84): false] call to method Assert + +# 87| [b (line 84): true] ... != ... +#-----| false -> [assertion failure, b (line 84): true] call to method Assert +#-----| true -> [assertion success, b (line 84): true] call to method Assert + +# 87| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 87| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 87| [b (line 84): false] null +#-----| -> [b (line 84): false] ... != ... + +# 87| [b (line 84): true] null +#-----| -> [b (line 84): true] ... != ... + +# 88| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 88| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 88| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 88| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 88| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 88| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 88| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 88| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 90| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 90| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 90| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 90| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 90| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 90| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 90| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 90| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 90| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 90| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 91| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 91| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 91| [assertion failure, b (line 84): false] call to method IsNull +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 91| [assertion failure, b (line 84): true] call to method IsNull +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 91| [assertion success, b (line 84): false] call to method IsNull +#-----| -> [b (line 84): false] ...; + +# 91| [assertion success, b (line 84): true] call to method IsNull +#-----| -> [b (line 84): true] ...; + +# 91| [b (line 84): false] access to local variable s +#-----| non-null -> [assertion failure, b (line 84): false] call to method IsNull +#-----| null -> [assertion success, b (line 84): false] call to method IsNull + +# 91| [b (line 84): true] access to local variable s +#-----| non-null -> [assertion failure, b (line 84): true] call to method IsNull +#-----| null -> [assertion success, b (line 84): true] call to method IsNull + +# 92| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 92| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 92| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 92| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 92| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 92| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 92| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 92| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 94| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 94| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 94| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 94| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 94| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 94| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 94| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 94| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 94| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 94| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 95| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 95| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 95| [assertion failure, b (line 84): false] call to method IsNotNull +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 95| [assertion failure, b (line 84): true] call to method IsNotNull +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 95| [assertion success, b (line 84): false] call to method IsNotNull +#-----| -> [b (line 84): false] ...; + +# 95| [assertion success, b (line 84): true] call to method IsNotNull +#-----| -> [b (line 84): true] ...; + +# 95| [b (line 84): false] access to local variable s +#-----| null -> [assertion failure, b (line 84): false] call to method IsNotNull +#-----| non-null -> [assertion success, b (line 84): false] call to method IsNotNull + +# 95| [b (line 84): true] access to local variable s +#-----| null -> [assertion failure, b (line 84): true] call to method IsNotNull +#-----| non-null -> [assertion success, b (line 84): true] call to method IsNotNull + +# 96| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 96| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 96| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 96| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 96| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 96| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 96| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 96| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 98| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 98| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 98| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 98| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 98| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 98| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 98| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 98| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 98| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 98| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 99| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 99| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 99| [assertion failure, b (line 84): false] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 99| [assertion failure, b (line 84): true] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 99| [assertion success, b (line 84): false] call to method IsTrue +#-----| -> [b (line 84): false] ...; + +# 99| [assertion success, b (line 84): true] call to method IsTrue +#-----| -> [b (line 84): true] ...; + +# 99| [b (line 84): false] ... == ... +#-----| false -> [assertion failure, b (line 84): false] call to method IsTrue +#-----| true -> [assertion success, b (line 84): false] call to method IsTrue + +# 99| [b (line 84): true] ... == ... +#-----| false -> [assertion failure, b (line 84): true] call to method IsTrue +#-----| true -> [assertion success, b (line 84): true] call to method IsTrue + +# 99| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 99| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 99| [b (line 84): false] null +#-----| -> [b (line 84): false] ... == ... + +# 99| [b (line 84): true] null +#-----| -> [b (line 84): true] ... == ... + +# 100| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 100| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 100| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 100| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 100| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 100| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 100| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 100| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 102| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 102| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 102| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 102| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 102| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 102| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 102| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 102| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 102| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 102| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 103| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 103| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 103| [assertion failure, b (line 84): false] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 103| [assertion failure, b (line 84): true] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 103| [assertion success, b (line 84): false] call to method IsTrue +#-----| -> [b (line 84): false] ...; + +# 103| [assertion success, b (line 84): true] call to method IsTrue +#-----| -> [b (line 84): true] ...; + +# 103| [b (line 84): false] ... != ... +#-----| false -> [assertion failure, b (line 84): false] call to method IsTrue +#-----| true -> [assertion success, b (line 84): false] call to method IsTrue + +# 103| [b (line 84): true] ... != ... +#-----| false -> [assertion failure, b (line 84): true] call to method IsTrue +#-----| true -> [assertion success, b (line 84): true] call to method IsTrue + +# 103| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 103| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 103| [b (line 84): false] null +#-----| -> [b (line 84): false] ... != ... + +# 103| [b (line 84): true] null +#-----| -> [b (line 84): true] ... != ... + +# 104| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 104| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 104| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 104| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 104| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 104| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 104| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 104| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 106| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 106| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 106| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 106| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 106| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 106| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 106| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 106| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 106| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 106| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 107| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 107| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 107| [assertion failure, b (line 84): false] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 107| [assertion failure, b (line 84): true] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 107| [assertion success, b (line 84): false] call to method IsFalse +#-----| -> [b (line 84): false] ...; + +# 107| [assertion success, b (line 84): true] call to method IsFalse +#-----| -> [b (line 84): true] ...; + +# 107| [b (line 84): false] ... != ... +#-----| true -> [assertion failure, b (line 84): false] call to method IsFalse +#-----| false -> [assertion success, b (line 84): false] call to method IsFalse + +# 107| [b (line 84): true] ... != ... +#-----| true -> [assertion failure, b (line 84): true] call to method IsFalse +#-----| false -> [assertion success, b (line 84): true] call to method IsFalse + +# 107| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 107| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 107| [b (line 84): false] null +#-----| -> [b (line 84): false] ... != ... + +# 107| [b (line 84): true] null +#-----| -> [b (line 84): true] ... != ... + +# 108| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 108| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 108| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 108| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 108| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 108| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 108| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 108| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 110| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 110| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 110| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 110| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 110| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 110| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 110| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 110| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 110| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 110| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 111| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 111| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 111| [assertion failure, b (line 84): false] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 111| [assertion failure, b (line 84): true] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 111| [assertion success, b (line 84): false] call to method IsFalse +#-----| -> [b (line 84): false] ...; + +# 111| [assertion success, b (line 84): true] call to method IsFalse +#-----| -> [b (line 84): true] ...; + +# 111| [b (line 84): false] ... == ... +#-----| true -> [assertion failure, b (line 84): false] call to method IsFalse +#-----| false -> [assertion success, b (line 84): false] call to method IsFalse + +# 111| [b (line 84): true] ... == ... +#-----| true -> [assertion failure, b (line 84): true] call to method IsFalse +#-----| false -> [assertion success, b (line 84): true] call to method IsFalse + +# 111| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 111| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 111| [b (line 84): false] null +#-----| -> [b (line 84): false] ... == ... + +# 111| [b (line 84): true] null +#-----| -> [b (line 84): true] ... == ... + +# 112| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 112| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 112| [b (line 84): false] call to method WriteLine +#-----| -> [b (line 84): false] ...; + +# 112| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 112| [b (line 84): false] access to property Length +#-----| -> [b (line 84): false] call to method WriteLine + +# 112| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 112| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] access to property Length + +# 112| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 114| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to parameter b + +# 114| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 114| [b (line 84): false] ... = ... +#-----| -> [b (line 84): false] ...; + +# 114| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 114| [b (line 84): false] ... ? ... : ... +#-----| -> [b (line 84): false] ... = ... + +# 114| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 114| [b (line 84): false] access to parameter b +#-----| false -> [b (line 84): false] "" + +# 114| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 114| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 114| [b (line 84): false] "" +#-----| -> [b (line 84): false] ... ? ... : ... + +# 115| [b (line 84): false] ...; +#-----| -> [b (line 84): false] access to local variable s + +# 115| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 115| [assertion failure, b (line 84): false] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 115| [assertion failure, b (line 84): true] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 115| [assertion success, b (line 84): true] call to method IsTrue +#-----| -> [b (line 84): true] ...; + +# 115| [false, b (line 84): false] ... && ... +#-----| false -> [assertion failure, b (line 84): false] call to method IsTrue + +# 115| [false, b (line 84): true] ... && ... +#-----| false -> [assertion failure, b (line 84): true] call to method IsTrue + +# 115| [true, b (line 84): true] ... && ... +#-----| true -> [assertion success, b (line 84): true] call to method IsTrue + +# 115| [b (line 84): false] ... != ... +#-----| false -> [false, b (line 84): false] ... && ... +#-----| true -> [b (line 84): false] access to parameter b + +# 115| [b (line 84): true] ... != ... +#-----| false -> [false, b (line 84): true] ... && ... +#-----| true -> [b (line 84): true] access to parameter b + +# 115| [b (line 84): false] access to local variable s +#-----| -> [b (line 84): false] null + +# 115| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 115| [b (line 84): false] null +#-----| -> [b (line 84): false] ... != ... + +# 115| [b (line 84): true] null +#-----| -> [b (line 84): true] ... != ... + +# 115| [b (line 84): false] access to parameter b +#-----| false -> [false, b (line 84): false] ... && ... + +# 115| [b (line 84): true] access to parameter b +#-----| true -> [true, b (line 84): true] ... && ... + +# 116| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 116| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 116| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 116| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 118| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 118| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 118| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 118| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 118| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 119| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 119| [assertion failure, b (line 84): true] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 119| [assertion success, b (line 84): true] call to method IsFalse +#-----| -> [b (line 84): true] ...; + +# 119| [false, b (line 84): true] ... || ... +#-----| false -> [assertion success, b (line 84): true] call to method IsFalse + +# 119| [true, b (line 84): true] ... || ... +#-----| true -> [assertion failure, b (line 84): true] call to method IsFalse + +# 119| [b (line 84): true] ... == ... +#-----| true -> [true, b (line 84): true] ... || ... +#-----| false -> [b (line 84): true] access to parameter b + +# 119| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 119| [b (line 84): true] null +#-----| -> [b (line 84): true] ... == ... + +# 119| [false, b (line 84): true] !... +#-----| false -> [false, b (line 84): true] ... || ... + +# 119| [b (line 84): true] access to parameter b +#-----| true -> [false, b (line 84): true] !... + +# 120| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 120| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 120| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 120| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 122| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 122| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 122| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 122| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 122| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 123| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 123| [assertion failure, b (line 84): true] call to method IsTrue +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 123| [assertion success, b (line 84): true] call to method IsTrue +#-----| -> [b (line 84): true] ...; + +# 123| [false, b (line 84): true] ... && ... +#-----| false -> [assertion failure, b (line 84): true] call to method IsTrue + +# 123| [true, b (line 84): true] ... && ... +#-----| true -> [assertion success, b (line 84): true] call to method IsTrue + +# 123| [b (line 84): true] ... == ... +#-----| false -> [false, b (line 84): true] ... && ... +#-----| true -> [b (line 84): true] access to parameter b + +# 123| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 123| [b (line 84): true] null +#-----| -> [b (line 84): true] ... == ... + +# 123| [b (line 84): true] access to parameter b +#-----| true -> [true, b (line 84): true] ... && ... + +# 124| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 124| [b (line 84): true] call to method WriteLine +#-----| -> [b (line 84): true] ...; + +# 124| [b (line 84): true] access to property Length +#-----| -> [b (line 84): true] call to method WriteLine + +# 124| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] access to property Length + +# 126| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to parameter b + +# 126| [b (line 84): true] ... = ... +#-----| -> [b (line 84): true] ...; + +# 126| [b (line 84): true] ... ? ... : ... +#-----| -> [b (line 84): true] ... = ... + +# 126| [b (line 84): true] access to parameter b +#-----| true -> [b (line 84): true] null + +# 126| [b (line 84): true] null +#-----| -> [b (line 84): true] ... ? ... : ... + +# 127| [b (line 84): true] ...; +#-----| -> [b (line 84): true] access to local variable s + +# 127| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit M12 (abnormal) + +# 127| [assertion success] call to method IsFalse +#-----| -> ...; + +# 127| [false] ... || ... +#-----| false -> [assertion success] call to method IsFalse + +# 127| [true] ... || ... +#-----| true -> [assertion failure] call to method IsFalse + +# 127| [b (line 84): true] ... != ... +#-----| true -> [true] ... || ... +#-----| false -> [b (line 84): true] access to parameter b + +# 127| [b (line 84): true] access to local variable s +#-----| -> [b (line 84): true] null + +# 127| [b (line 84): true] null +#-----| -> [b (line 84): true] ... != ... + +# 127| [false] !... +#-----| false -> [false] ... || ... + +# 127| [b (line 84): true] access to parameter b +#-----| true -> [false] !... + +# 128| ...; +#-----| -> access to local variable s + +# 128| call to method WriteLine +#-----| -> exit M12 (normal) + +# 128| access to property Length +#-----| -> call to method WriteLine + +# 128| access to local variable s +#-----| -> access to property Length + +# 131| enter AssertTrueFalse +#-----| -> {...} + +# 131| exit AssertTrueFalse + +# 131| exit AssertTrueFalse (normal) +#-----| -> exit AssertTrueFalse + +# 135| {...} +#-----| -> exit AssertTrueFalse (normal) + +# 138| enter M13 +#-----| -> {...} + +# 138| exit M13 + +# 138| exit M13 (abnormal) +#-----| -> exit M13 + +# 138| exit M13 (normal) +#-----| -> exit M13 + +# 139| {...} +#-----| -> ...; + +# 140| ...; +#-----| -> this access + +# 140| [assertion failure] call to method AssertTrueFalse +#-----| exception(Exception) -> exit M13 (abnormal) + +# 140| [assertion failure] call to method AssertTrueFalse +#-----| exception(Exception) -> exit M13 (abnormal) + +# 140| [assertion success] call to method AssertTrueFalse +#-----| -> return ...; + +# 140| this access +#-----| -> access to parameter b1 + +# 140| access to parameter b1 +#-----| true -> access to parameter b2 +#-----| false -> [assertion failure] access to parameter b2 + +# 140| access to parameter b2 +#-----| true -> [assertion failure] access to parameter b3 +#-----| false -> [assertion success] access to parameter b3 + +# 140| [assertion failure] access to parameter b2 +#-----| true -> [assertion failure] access to parameter b3 + +# 140| [assertion failure] access to parameter b3 +#-----| -> [assertion failure] call to method AssertTrueFalse + +# 140| [assertion failure] access to parameter b3 +#-----| -> [assertion failure] call to method AssertTrueFalse + +# 140| [assertion success] access to parameter b3 +#-----| -> [assertion success] call to method AssertTrueFalse + +# 141| return ...; +#-----| return -> exit M13 (normal) + +Assignments.cs: +# 3| enter M +#-----| -> {...} + +# 3| exit M + +# 3| exit M (normal) +#-----| -> exit M + +# 4| {...} +#-----| -> ... ...; + +# 5| ... ...; +#-----| -> 0 + +# 5| Int32 x = ... +#-----| -> ...; + +# 5| 0 +#-----| -> Int32 x = ... + +# 6| ...; +#-----| -> access to local variable x + +# 6| ... = ... +#-----| -> ... ...; + +# 6| ... + ... +#-----| -> ... = ... + +# 6| access to local variable x +#-----| -> 1 + +# 6| 1 +#-----| -> ... + ... + +# 8| ... ...; +#-----| -> 0 + +# 8| dynamic d = ... +#-----| -> ...; + +# 8| (...) ... +#-----| -> dynamic d = ... + +# 8| 0 +#-----| -> (...) ... + +# 9| ...; +#-----| -> access to local variable d + +# 9| ... = ... +#-----| -> ... ...; + +# 9| dynamic call to operator - +#-----| -> ... = ... + +# 9| access to local variable d +#-----| -> 2 + +# 9| 2 +#-----| -> dynamic call to operator - + +# 11| ... ...; +#-----| -> object creation of type Assignments + +# 11| Assignments a = ... +#-----| -> ...; + +# 11| object creation of type Assignments +#-----| -> Assignments a = ... + +# 12| ...; +#-----| -> access to local variable a + +# 12| ... = ... +#-----| -> ...; + +# 12| call to operator + +#-----| -> ... = ... + +# 12| access to local variable a +#-----| -> this access + +# 12| this access +#-----| -> call to operator + + +# 14| ...; +#-----| -> this access + +# 14| ... += ... +#-----| -> exit M (normal) + +# 14| access to event Event +#-----| -> ... += ... + +# 14| this access +#-----| -> (...) => ... + +# 14| enter (...) => ... +#-----| -> {...} + +# 14| (...) => ... +#-----| -> access to event Event + +# 14| exit (...) => ... + +# 14| exit (...) => ... (normal) +#-----| -> exit (...) => ... + +# 14| {...} +#-----| -> exit (...) => ... (normal) + +# 17| enter + +#-----| -> {...} + +# 17| exit + + +# 17| exit + (normal) +#-----| -> exit + + +# 18| {...} +#-----| -> access to parameter x + +# 19| return ...; +#-----| return -> exit + (normal) + +# 19| access to parameter x +#-----| -> return ...; + +BreakInTry.cs: +# 3| enter M1 +#-----| -> {...} + +# 3| exit M1 + +# 3| exit M1 (normal) +#-----| -> exit M1 + +# 4| {...} +#-----| -> try {...} ... + +# 5| try {...} ... +#-----| -> {...} + +# 6| {...} +#-----| -> access to parameter args + +# 7| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> {...} + +# 7| String arg +#-----| -> {...} + +# 7| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 8| {...} +#-----| -> if (...) ... + +# 9| if (...) ... +#-----| -> access to local variable arg + +# 9| ... == ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> break; + +# 9| access to local variable arg +#-----| -> null + +# 9| null +#-----| -> ... == ... + +# 10| break; +#-----| break -> {...} + +# 14| {...} +#-----| -> if (...) ... + +# 15| if (...) ... +#-----| -> access to parameter args + +# 15| ... == ... +#-----| true -> ; +#-----| false -> exit M1 (normal) + +# 15| access to parameter args +#-----| -> null + +# 15| null +#-----| -> ... == ... + +# 16| ; +#-----| -> exit M1 (normal) + +# 20| enter M2 +#-----| -> {...} + +# 20| exit M2 + +# 20| exit M2 (normal) +#-----| -> exit M2 + +# 21| {...} +#-----| -> access to parameter args + +# 22| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> ; + +# 22| String arg +#-----| -> {...} + +# 22| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 23| {...} +#-----| -> try {...} ... + +# 24| try {...} ... +#-----| -> {...} + +# 25| {...} +#-----| -> if (...) ... + +# 26| if (...) ... +#-----| -> access to local variable arg + +# 26| ... == ... +#-----| true -> break; +#-----| false -> {...} + +# 26| access to local variable arg +#-----| -> null + +# 26| null +#-----| -> ... == ... + +# 27| break; +#-----| break -> [finally: break] {...} + +# 30| {...} +#-----| -> if (...) ... + +# 30| [finally: break] {...} +#-----| -> [finally: break] if (...) ... + +# 31| if (...) ... +#-----| -> access to parameter args + +# 31| [finally: break] if (...) ... +#-----| -> [finally: break] access to parameter args + +# 31| ... == ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> ; + +# 31| [finally: break] ... == ... +#-----| true -> [finally: break] ; +#-----| false -> ; + +# 31| access to parameter args +#-----| -> null + +# 31| [finally: break] access to parameter args +#-----| -> [finally: break] null + +# 31| null +#-----| -> ... == ... + +# 31| [finally: break] null +#-----| -> [finally: break] ... == ... + +# 32| ; +#-----| -> foreach (... ... in ...) ... + +# 32| [finally: break] ; +#-----| break -> ; + +# 35| ; +#-----| -> exit M2 (normal) + +# 38| enter M3 +#-----| -> {...} + +# 38| exit M3 + +# 38| exit M3 (normal) +#-----| -> exit M3 + +# 39| {...} +#-----| -> try {...} ... + +# 40| try {...} ... +#-----| -> {...} + +# 41| {...} +#-----| -> if (...) ... + +# 42| if (...) ... +#-----| -> access to parameter args + +# 42| ... == ... +#-----| true -> return ...; +#-----| false -> {...} + +# 42| access to parameter args +#-----| -> null + +# 42| null +#-----| -> ... == ... + +# 43| return ...; +#-----| return -> [finally: return] {...} + +# 46| {...} +#-----| -> access to parameter args + +# 46| [finally: return] {...} +#-----| -> [finally: return] access to parameter args + +# 47| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> ; + +# 47| [finally: return] foreach (... ... in ...) ... +#-----| non-empty -> [finally: return] String arg +#-----| return -> exit M3 (normal) + +# 47| String arg +#-----| -> {...} + +# 47| [finally: return] String arg +#-----| -> [finally: return] {...} + +# 47| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 47| [finally: return] access to parameter args +#-----| -> [finally: return] foreach (... ... in ...) ... + +# 48| {...} +#-----| -> if (...) ... + +# 48| [finally: return] {...} +#-----| -> [finally: return] if (...) ... + +# 49| if (...) ... +#-----| -> access to local variable arg + +# 49| [finally: return] if (...) ... +#-----| -> [finally: return] access to local variable arg + +# 49| ... == ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> break; + +# 49| [finally: return] ... == ... +#-----| false -> [finally: return] foreach (... ... in ...) ... +#-----| true -> [finally: return] break; + +# 49| access to local variable arg +#-----| -> null + +# 49| [finally: return] access to local variable arg +#-----| -> [finally: return] null + +# 49| null +#-----| -> ... == ... + +# 49| [finally: return] null +#-----| -> [finally: return] ... == ... + +# 50| break; +#-----| break -> ; + +# 50| [finally: return] break; +#-----| return -> exit M3 (normal) + +# 53| ; +#-----| -> exit M3 (normal) + +# 56| enter M4 +#-----| -> {...} + +# 56| exit M4 + +# 56| exit M4 (normal) +#-----| -> exit M4 + +# 57| {...} +#-----| -> try {...} ... + +# 58| try {...} ... +#-----| -> {...} + +# 59| {...} +#-----| -> if (...) ... + +# 60| if (...) ... +#-----| -> access to parameter args + +# 60| ... == ... +#-----| true -> return ...; +#-----| false -> {...} + +# 60| access to parameter args +#-----| -> null + +# 60| null +#-----| -> ... == ... + +# 61| return ...; +#-----| return -> [finally: return] {...} + +# 64| {...} +#-----| -> access to parameter args + +# 64| [finally: return] {...} +#-----| -> [finally: return] access to parameter args + +# 65| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> exit M4 (normal) + +# 65| [finally: return] foreach (... ... in ...) ... +#-----| non-empty -> [finally: return] String arg +#-----| return -> exit M4 (normal) + +# 65| String arg +#-----| -> {...} + +# 65| [finally: return] String arg +#-----| -> [finally: return] {...} + +# 65| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 65| [finally: return] access to parameter args +#-----| -> [finally: return] foreach (... ... in ...) ... + +# 66| {...} +#-----| -> if (...) ... + +# 66| [finally: return] {...} +#-----| -> [finally: return] if (...) ... + +# 67| if (...) ... +#-----| -> access to local variable arg + +# 67| [finally: return] if (...) ... +#-----| -> [finally: return] access to local variable arg + +# 67| ... == ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> break; + +# 67| [finally: return] ... == ... +#-----| false -> [finally: return] foreach (... ... in ...) ... +#-----| true -> [finally: return] break; + +# 67| access to local variable arg +#-----| -> null + +# 67| [finally: return] access to local variable arg +#-----| -> [finally: return] null + +# 67| null +#-----| -> ... == ... + +# 67| [finally: return] null +#-----| -> [finally: return] ... == ... + +# 68| break; +#-----| break -> exit M4 (normal) + +# 68| [finally: return] break; +#-----| return -> exit M4 (normal) + +CompileTimeOperators.cs: +# 5| enter Default +#-----| -> {...} + +# 5| exit Default + +# 5| exit Default (normal) +#-----| -> exit Default + +# 6| {...} +#-----| -> default(...) + +# 7| return ...; +#-----| return -> exit Default (normal) + +# 7| default(...) +#-----| -> return ...; + +# 10| enter Sizeof +#-----| -> {...} + +# 10| exit Sizeof + +# 10| exit Sizeof (normal) +#-----| -> exit Sizeof + +# 11| {...} +#-----| -> sizeof(..) + +# 12| return ...; +#-----| return -> exit Sizeof (normal) + +# 12| sizeof(..) +#-----| -> return ...; + +# 15| enter Typeof +#-----| -> {...} + +# 15| exit Typeof + +# 15| exit Typeof (normal) +#-----| -> exit Typeof + +# 16| {...} +#-----| -> typeof(...) + +# 17| return ...; +#-----| return -> exit Typeof (normal) + +# 17| typeof(...) +#-----| -> return ...; + +# 20| enter Nameof +#-----| -> {...} + +# 20| exit Nameof + +# 20| exit Nameof (normal) +#-----| -> exit Nameof + +# 21| {...} +#-----| -> nameof(...) + +# 22| return ...; +#-----| return -> exit Nameof (normal) + +# 22| nameof(...) +#-----| -> return ...; + +# 28| enter M +#-----| -> {...} + +# 28| exit M + +# 28| exit M (normal) +#-----| -> exit M + +# 29| {...} +#-----| -> try {...} ... + +# 30| try {...} ... +#-----| -> {...} + +# 31| {...} +#-----| -> goto ...; + +# 32| goto ...; +#-----| goto(End) -> [finally: goto(End)] {...} + +# 36| [finally: goto(End)] {...} +#-----| -> [finally: goto(End)] ...; + +# 37| [finally: goto(End)] ...; +#-----| -> [finally: goto(End)] "Finally" + +# 37| [finally: goto(End)] call to method WriteLine +#-----| goto(End) -> End: + +# 37| [finally: goto(End)] "Finally" +#-----| -> [finally: goto(End)] call to method WriteLine + +# 40| End: +#-----| -> ...; + +# 40| ...; +#-----| -> "End" + +# 40| call to method WriteLine +#-----| -> exit M (normal) + +# 40| "End" +#-----| -> call to method WriteLine + +ConditionalAccess.cs: +# 3| enter M1 +#-----| -> access to parameter i + +# 3| exit M1 + +# 3| exit M1 (normal) +#-----| -> exit M1 + +# 3| access to parameter i +#-----| non-null -> call to method ToString +#-----| null -> exit M1 (normal) + +# 3| call to method ToString +#-----| non-null -> call to method ToLower +#-----| null -> exit M1 (normal) + +# 3| call to method ToLower +#-----| -> exit M1 (normal) + +# 5| enter M2 +#-----| -> access to parameter s + +# 5| exit M2 + +# 5| exit M2 (normal) +#-----| -> exit M2 + +# 5| access to parameter s +#-----| non-null -> access to property Length +#-----| null -> exit M2 (normal) + +# 5| access to property Length +#-----| -> exit M2 (normal) + +# 7| enter M3 +#-----| -> access to parameter s1 + +# 7| exit M3 + +# 7| exit M3 (normal) +#-----| -> exit M3 + +# 7| ... ?? ... +#-----| non-null -> access to property Length +#-----| null -> exit M3 (normal) + +# 7| [non-null] ... ?? ... +#-----| non-null -> access to property Length + +# 7| [null] ... ?? ... +#-----| null -> exit M3 (normal) + +# 7| access to parameter s1 +#-----| non-null -> ... ?? ... +#-----| null -> access to parameter s2 + +# 7| access to parameter s2 +#-----| non-null -> [non-null] ... ?? ... +#-----| null -> [null] ... ?? ... + +# 7| access to property Length +#-----| -> exit M3 (normal) + +# 9| enter M4 +#-----| -> access to parameter s + +# 9| exit M4 + +# 9| exit M4 (normal) +#-----| -> exit M4 + +# 9| ... ?? ... +#-----| -> exit M4 (normal) + +# 9| access to parameter s +#-----| non-null -> access to property Length +#-----| null -> 0 + +# 9| access to property Length +#-----| non-null -> ... ?? ... +#-----| null -> 0 + +# 9| 0 +#-----| -> ... ?? ... + +# 11| enter M5 +#-----| -> {...} + +# 11| exit M5 + +# 11| exit M5 (normal) +#-----| -> exit M5 + +# 12| {...} +#-----| -> if (...) ... + +# 13| if (...) ... +#-----| -> access to parameter s + +# 13| ... > ... +#-----| true -> 0 +#-----| false -> 1 + +# 13| access to parameter s +#-----| non-null -> access to property Length +#-----| null -> 0 + +# 13| access to property Length +#-----| -> 0 + +# 13| (...) ... +#-----| -> ... > ... + +# 13| 0 +#-----| -> (...) ... + +# 14| return ...; +#-----| return -> exit M5 (normal) + +# 14| 0 +#-----| -> return ...; + +# 16| return ...; +#-----| return -> exit M5 (normal) + +# 16| 1 +#-----| -> return ...; + +# 19| enter M6 +#-----| -> access to parameter s1 + +# 19| exit M6 + +# 19| exit M6 (normal) +#-----| -> exit M6 + +# 19| access to parameter s1 +#-----| non-null -> access to parameter s2 +#-----| null -> exit M6 (normal) + +# 19| call to method CommaJoinWith +#-----| -> exit M6 (normal) + +# 19| access to parameter s2 +#-----| -> call to method CommaJoinWith + +# 21| enter M7 +#-----| -> {...} + +# 21| exit M7 + +# 21| exit M7 (normal) +#-----| -> exit M7 + +# 22| {...} +#-----| -> ... ...; + +# 23| ... ...; +#-----| -> null + +# 23| Nullable j = ... +#-----| -> ... ...; + +# 23| (...) ... +#-----| null -> Nullable j = ... + +# 23| null +#-----| -> (...) ... + +# 24| ... ...; +#-----| -> access to parameter i + +# 24| String s = ... +#-----| -> ...; + +# 24| (...) ... +#-----| non-null -> call to method ToString + +# 24| access to parameter i +#-----| -> (...) ... + +# 24| call to method ToString +#-----| -> String s = ... + +# 25| ...; +#-----| -> "" + +# 25| ... = ... +#-----| -> exit M7 (normal) + +# 25| "" +#-----| non-null -> access to local variable s + +# 25| call to method CommaJoinWith +#-----| -> ... = ... + +# 25| access to local variable s +#-----| -> call to method CommaJoinWith + +# 30| enter Out +#-----| -> 0 + +# 30| exit Out + +# 30| exit Out (normal) +#-----| -> exit Out + +# 30| ... = ... +#-----| -> exit Out (normal) + +# 30| 0 +#-----| -> ... = ... + +# 32| enter M8 +#-----| -> {...} + +# 32| exit M8 + +# 32| exit M8 (normal) +#-----| -> exit M8 + +# 33| {...} +#-----| -> ...; + +# 34| ...; +#-----| -> 0 + +# 34| ... = ... +#-----| -> ...; + +# 34| 0 +#-----| -> ... = ... + +# 35| ...; +#-----| -> this access + +# 35| access to property Prop +#-----| non-null -> call to method Out +#-----| null -> exit M8 (normal) + +# 35| this access +#-----| -> access to property Prop + +# 35| call to method Out +#-----| -> exit M8 (normal) + +# 41| enter CommaJoinWith +#-----| -> access to parameter s1 + +# 41| exit CommaJoinWith + +# 41| exit CommaJoinWith (normal) +#-----| -> exit CommaJoinWith + +# 41| ... + ... +#-----| -> exit CommaJoinWith (normal) + +# 41| ... + ... +#-----| -> access to parameter s2 + +# 41| access to parameter s1 +#-----| -> ", " + +# 41| ", " +#-----| -> ... + ... + +# 41| access to parameter s2 +#-----| -> ... + ... + +Conditions.cs: +# 3| enter IncrOrDecr +#-----| -> {...} + +# 3| exit IncrOrDecr + +# 3| exit IncrOrDecr (normal) +#-----| -> exit IncrOrDecr + +# 4| {...} +#-----| -> if (...) ... + +# 5| if (...) ... +#-----| -> access to parameter inc + +# 5| access to parameter inc +#-----| true -> [inc (line 3): true] ...; +#-----| false -> [inc (line 3): false] if (...) ... + +# 6| [inc (line 3): true] ...; +#-----| -> [inc (line 3): true] access to parameter x + +# 6| [inc (line 3): true] ...++ +#-----| -> [inc (line 3): true] if (...) ... + +# 6| [inc (line 3): true] access to parameter x +#-----| -> [inc (line 3): true] ...++ + +# 7| [inc (line 3): false] if (...) ... +#-----| -> [inc (line 3): false] access to parameter inc + +# 7| [inc (line 3): true] if (...) ... +#-----| -> [inc (line 3): true] access to parameter inc + +# 7| [false] !... +#-----| false -> exit IncrOrDecr (normal) + +# 7| [true] !... +#-----| true -> ...; + +# 7| [inc (line 3): false] access to parameter inc +#-----| false -> [true] !... + +# 7| [inc (line 3): true] access to parameter inc +#-----| true -> [false] !... + +# 8| ...; +#-----| -> access to parameter x + +# 8| ...-- +#-----| -> exit IncrOrDecr (normal) + +# 8| access to parameter x +#-----| -> ...-- + +# 11| enter M1 +#-----| -> {...} + +# 11| exit M1 + +# 11| exit M1 (normal) +#-----| -> exit M1 + +# 12| {...} +#-----| -> ... ...; + +# 13| ... ...; +#-----| -> 0 + +# 13| Int32 x = ... +#-----| -> if (...) ... + +# 13| 0 +#-----| -> Int32 x = ... + +# 14| if (...) ... +#-----| -> access to parameter b + +# 14| access to parameter b +#-----| true -> [b (line 11): true] ...; +#-----| false -> [b (line 11): false] if (...) ... + +# 15| [b (line 11): true] ...; +#-----| -> [b (line 11): true] access to local variable x + +# 15| [b (line 11): true] ...++ +#-----| -> [b (line 11): true] if (...) ... + +# 15| [b (line 11): true] access to local variable x +#-----| -> [b (line 11): true] ...++ + +# 16| [b (line 11): false] if (...) ... +#-----| -> [b (line 11): false] access to local variable x + +# 16| [b (line 11): true] if (...) ... +#-----| -> [b (line 11): true] access to local variable x + +# 16| [b (line 11): false] ... > ... +#-----| true -> [b (line 11): false] if (...) ... +#-----| false -> access to local variable x + +# 16| [b (line 11): true] ... > ... +#-----| true -> [b (line 11): true] if (...) ... +#-----| false -> access to local variable x + +# 16| [b (line 11): false] access to local variable x +#-----| -> [b (line 11): false] 0 + +# 16| [b (line 11): true] access to local variable x +#-----| -> [b (line 11): true] 0 + +# 16| [b (line 11): false] 0 +#-----| -> [b (line 11): false] ... > ... + +# 16| [b (line 11): true] 0 +#-----| -> [b (line 11): true] ... > ... + +# 17| [b (line 11): false] if (...) ... +#-----| -> [b (line 11): false] access to parameter b + +# 17| [b (line 11): true] if (...) ... +#-----| -> [b (line 11): true] access to parameter b + +# 17| [false] !... +#-----| false -> access to local variable x + +# 17| [true] !... +#-----| true -> ...; + +# 17| [b (line 11): false] access to parameter b +#-----| false -> [true] !... + +# 17| [b (line 11): true] access to parameter b +#-----| true -> [false] !... + +# 18| ...; +#-----| -> access to local variable x + +# 18| ...-- +#-----| -> access to local variable x + +# 18| access to local variable x +#-----| -> ...-- + +# 19| return ...; +#-----| return -> exit M1 (normal) + +# 19| access to local variable x +#-----| -> return ...; + +# 22| enter M2 +#-----| -> {...} + +# 22| exit M2 + +# 22| exit M2 (normal) +#-----| -> exit M2 + +# 23| {...} +#-----| -> ... ...; + +# 24| ... ...; +#-----| -> 0 + +# 24| Int32 x = ... +#-----| -> if (...) ... + +# 24| 0 +#-----| -> Int32 x = ... + +# 25| if (...) ... +#-----| -> access to parameter b1 + +# 25| access to parameter b1 +#-----| true -> if (...) ... +#-----| false -> if (...) ... + +# 26| if (...) ... +#-----| -> access to parameter b2 + +# 26| access to parameter b2 +#-----| true -> [b2 (line 22): true] ...; +#-----| false -> [b2 (line 22): false] if (...) ... + +# 27| [b2 (line 22): true] ...; +#-----| -> [b2 (line 22): true] access to local variable x + +# 27| [b2 (line 22): true] ...++ +#-----| -> [b2 (line 22): true] if (...) ... + +# 27| [b2 (line 22): true] access to local variable x +#-----| -> [b2 (line 22): true] ...++ + +# 28| if (...) ... +#-----| -> access to parameter b2 + +# 28| [b2 (line 22): false] if (...) ... +#-----| -> [b2 (line 22): false] access to parameter b2 + +# 28| [b2 (line 22): true] if (...) ... +#-----| -> [b2 (line 22): true] access to parameter b2 + +# 28| access to parameter b2 +#-----| true -> ...; +#-----| false -> access to local variable x + +# 28| [b2 (line 22): false] access to parameter b2 +#-----| false -> access to local variable x + +# 28| [b2 (line 22): true] access to parameter b2 +#-----| true -> ...; + +# 29| ...; +#-----| -> access to local variable x + +# 29| ...++ +#-----| -> access to local variable x + +# 29| access to local variable x +#-----| -> ...++ + +# 30| return ...; +#-----| return -> exit M2 (normal) + +# 30| access to local variable x +#-----| -> return ...; + +# 33| enter M3 +#-----| -> {...} + +# 33| exit M3 + +# 33| exit M3 (normal) +#-----| -> exit M3 + +# 34| {...} +#-----| -> ... ...; + +# 35| ... ...; +#-----| -> 0 + +# 35| Int32 x = ... +#-----| -> ... ...; + +# 35| 0 +#-----| -> Int32 x = ... + +# 36| ... ...; +#-----| -> false + +# 36| Boolean b2 = ... +#-----| -> if (...) ... + +# 36| false +#-----| -> Boolean b2 = ... + +# 37| if (...) ... +#-----| -> access to parameter b1 + +# 37| access to parameter b1 +#-----| true -> ...; +#-----| false -> if (...) ... + +# 38| ...; +#-----| -> access to parameter b1 + +# 38| ... = ... +#-----| -> if (...) ... + +# 38| access to parameter b1 +#-----| -> ... = ... + +# 39| if (...) ... +#-----| -> access to local variable b2 + +# 39| access to local variable b2 +#-----| true -> [b2 (line 39): true] ...; +#-----| false -> [b2 (line 39): false] if (...) ... + +# 40| [b2 (line 39): true] ...; +#-----| -> [b2 (line 39): true] access to local variable x + +# 40| [b2 (line 39): true] ...++ +#-----| -> [b2 (line 39): true] if (...) ... + +# 40| [b2 (line 39): true] access to local variable x +#-----| -> [b2 (line 39): true] ...++ + +# 41| [b2 (line 39): false] if (...) ... +#-----| -> [b2 (line 39): false] access to local variable b2 + +# 41| [b2 (line 39): true] if (...) ... +#-----| -> [b2 (line 39): true] access to local variable b2 + +# 41| [b2 (line 39): false] access to local variable b2 +#-----| false -> access to local variable x + +# 41| [b2 (line 39): true] access to local variable b2 +#-----| true -> ...; + +# 42| ...; +#-----| -> access to local variable x + +# 42| ...++ +#-----| -> access to local variable x + +# 42| access to local variable x +#-----| -> ...++ + +# 43| return ...; +#-----| return -> exit M3 (normal) + +# 43| access to local variable x +#-----| -> return ...; + +# 46| enter M4 +#-----| -> {...} + +# 46| exit M4 + +# 46| exit M4 (normal) +#-----| -> exit M4 + +# 47| {...} +#-----| -> ... ...; + +# 48| ... ...; +#-----| -> 0 + +# 48| Int32 y = ... +#-----| -> while (...) ... + +# 48| 0 +#-----| -> Int32 y = ... + +# 49| while (...) ... +#-----| -> access to parameter x + +# 49| ... > ... +#-----| true -> {...} +#-----| false -> access to local variable y + +# 49| [b (line 46): false] ... > ... +#-----| true -> [b (line 46): false] {...} +#-----| false -> access to local variable y + +# 49| [b (line 46): true] ... > ... +#-----| true -> [b (line 46): true] {...} +#-----| false -> access to local variable y + +# 49| ...-- +#-----| -> 0 + +# 49| [b (line 46): false] ...-- +#-----| -> [b (line 46): false] 0 + +# 49| [b (line 46): true] ...-- +#-----| -> [b (line 46): true] 0 + +# 49| access to parameter x +#-----| -> ...-- + +# 49| [b (line 46): false] access to parameter x +#-----| -> [b (line 46): false] ...-- + +# 49| [b (line 46): true] access to parameter x +#-----| -> [b (line 46): true] ...-- + +# 49| 0 +#-----| -> ... > ... + +# 49| [b (line 46): false] 0 +#-----| -> [b (line 46): false] ... > ... + +# 49| [b (line 46): true] 0 +#-----| -> [b (line 46): true] ... > ... + +# 50| {...} +#-----| -> if (...) ... + +# 50| [b (line 46): false] {...} +#-----| -> [b (line 46): false] if (...) ... + +# 50| [b (line 46): true] {...} +#-----| -> [b (line 46): true] if (...) ... + +# 51| if (...) ... +#-----| -> access to parameter b + +# 51| [b (line 46): false] if (...) ... +#-----| -> [b (line 46): false] access to parameter b + +# 51| [b (line 46): true] if (...) ... +#-----| -> [b (line 46): true] access to parameter b + +# 51| access to parameter b +#-----| true -> [b (line 46): true] ...; +#-----| false -> [b (line 46): false] access to parameter x + +# 51| [b (line 46): false] access to parameter b +#-----| false -> [b (line 46): false] access to parameter x + +# 51| [b (line 46): true] access to parameter b +#-----| true -> [b (line 46): true] ...; + +# 52| [b (line 46): true] ...; +#-----| -> [b (line 46): true] access to local variable y + +# 52| [b (line 46): true] ...++ +#-----| -> [b (line 46): true] access to parameter x + +# 52| [b (line 46): true] access to local variable y +#-----| -> [b (line 46): true] ...++ + +# 54| return ...; +#-----| return -> exit M4 (normal) + +# 54| access to local variable y +#-----| -> return ...; + +# 57| enter M5 +#-----| -> {...} + +# 57| exit M5 + +# 57| exit M5 (normal) +#-----| -> exit M5 + +# 58| {...} +#-----| -> ... ...; + +# 59| ... ...; +#-----| -> 0 + +# 59| Int32 y = ... +#-----| -> while (...) ... + +# 59| 0 +#-----| -> Int32 y = ... + +# 60| while (...) ... +#-----| -> access to parameter x + +# 60| ... > ... +#-----| true -> {...} +#-----| false -> if (...) ... + +# 60| [b (line 57): false] ... > ... +#-----| true -> [b (line 57): false] {...} +#-----| false -> [b (line 57): false] if (...) ... + +# 60| [b (line 57): true] ... > ... +#-----| true -> [b (line 57): true] {...} +#-----| false -> [b (line 57): true] if (...) ... + +# 60| ...-- +#-----| -> 0 + +# 60| [b (line 57): false] ...-- +#-----| -> [b (line 57): false] 0 + +# 60| [b (line 57): true] ...-- +#-----| -> [b (line 57): true] 0 + +# 60| access to parameter x +#-----| -> ...-- + +# 60| [b (line 57): false] access to parameter x +#-----| -> [b (line 57): false] ...-- + +# 60| [b (line 57): true] access to parameter x +#-----| -> [b (line 57): true] ...-- + +# 60| 0 +#-----| -> ... > ... + +# 60| [b (line 57): false] 0 +#-----| -> [b (line 57): false] ... > ... + +# 60| [b (line 57): true] 0 +#-----| -> [b (line 57): true] ... > ... + +# 61| {...} +#-----| -> if (...) ... + +# 61| [b (line 57): false] {...} +#-----| -> [b (line 57): false] if (...) ... + +# 61| [b (line 57): true] {...} +#-----| -> [b (line 57): true] if (...) ... + +# 62| if (...) ... +#-----| -> access to parameter b + +# 62| [b (line 57): false] if (...) ... +#-----| -> [b (line 57): false] access to parameter b + +# 62| [b (line 57): true] if (...) ... +#-----| -> [b (line 57): true] access to parameter b + +# 62| access to parameter b +#-----| true -> [b (line 57): true] ...; +#-----| false -> [b (line 57): false] access to parameter x + +# 62| [b (line 57): false] access to parameter b +#-----| false -> [b (line 57): false] access to parameter x + +# 62| [b (line 57): true] access to parameter b +#-----| true -> [b (line 57): true] ...; + +# 63| [b (line 57): true] ...; +#-----| -> [b (line 57): true] access to local variable y + +# 63| [b (line 57): true] ...++ +#-----| -> [b (line 57): true] access to parameter x + +# 63| [b (line 57): true] access to local variable y +#-----| -> [b (line 57): true] ...++ + +# 65| if (...) ... +#-----| -> access to parameter b + +# 65| [b (line 57): false] if (...) ... +#-----| -> [b (line 57): false] access to parameter b + +# 65| [b (line 57): true] if (...) ... +#-----| -> [b (line 57): true] access to parameter b + +# 65| access to parameter b +#-----| true -> ...; +#-----| false -> access to local variable y + +# 65| [b (line 57): false] access to parameter b +#-----| false -> access to local variable y + +# 65| [b (line 57): true] access to parameter b +#-----| true -> ...; + +# 66| ...; +#-----| -> access to local variable y + +# 66| ...++ +#-----| -> access to local variable y + +# 66| access to local variable y +#-----| -> ...++ + +# 67| return ...; +#-----| return -> exit M5 (normal) + +# 67| access to local variable y +#-----| -> return ...; + +# 70| enter M6 +#-----| -> {...} + +# 70| exit M6 + +# 70| exit M6 (normal) +#-----| -> exit M6 + +# 71| {...} +#-----| -> ... ...; + +# 72| ... ...; +#-----| -> access to parameter ss + +# 72| Boolean b = ... +#-----| -> ... ...; + +# 72| ... > ... +#-----| -> Boolean b = ... + +# 72| access to property Length +#-----| -> 0 + +# 72| access to parameter ss +#-----| -> access to property Length + +# 72| 0 +#-----| -> ... > ... + +# 73| ... ...; +#-----| -> 0 + +# 73| Int32 x = ... +#-----| -> access to parameter ss + +# 73| 0 +#-----| -> Int32 x = ... + +# 74| foreach (... ... in ...) ... +#-----| non-empty -> String _ +#-----| empty -> if (...) ... + +# 74| String _ +#-----| -> {...} + +# 74| access to parameter ss +#-----| -> foreach (... ... in ...) ... + +# 75| {...} +#-----| -> if (...) ... + +# 76| if (...) ... +#-----| -> access to local variable b + +# 76| access to local variable b +#-----| true -> ...; +#-----| false -> if (...) ... + +# 77| ...; +#-----| -> access to local variable x + +# 77| ...++ +#-----| -> if (...) ... + +# 77| access to local variable x +#-----| -> ...++ + +# 78| if (...) ... +#-----| -> access to local variable x + +# 78| ... > ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> ...; + +# 78| access to local variable x +#-----| -> 0 + +# 78| 0 +#-----| -> ... > ... + +# 79| ...; +#-----| -> false + +# 79| ... = ... +#-----| -> foreach (... ... in ...) ... + +# 79| false +#-----| -> ... = ... + +# 81| if (...) ... +#-----| -> access to local variable b + +# 81| access to local variable b +#-----| true -> ...; +#-----| false -> access to local variable x + +# 82| ...; +#-----| -> access to local variable x + +# 82| ...++ +#-----| -> access to local variable x + +# 82| access to local variable x +#-----| -> ...++ + +# 83| return ...; +#-----| return -> exit M6 (normal) + +# 83| access to local variable x +#-----| -> return ...; + +# 86| enter M7 +#-----| -> {...} + +# 86| exit M7 + +# 86| exit M7 (normal) +#-----| -> exit M7 + +# 87| {...} +#-----| -> ... ...; + +# 88| ... ...; +#-----| -> access to parameter ss + +# 88| Boolean b = ... +#-----| -> ... ...; + +# 88| ... > ... +#-----| -> Boolean b = ... + +# 88| access to property Length +#-----| -> 0 + +# 88| access to parameter ss +#-----| -> access to property Length + +# 88| 0 +#-----| -> ... > ... + +# 89| ... ...; +#-----| -> 0 + +# 89| Int32 x = ... +#-----| -> access to parameter ss + +# 89| 0 +#-----| -> Int32 x = ... + +# 90| foreach (... ... in ...) ... +#-----| non-empty -> String _ +#-----| empty -> access to local variable x + +# 90| String _ +#-----| -> {...} + +# 90| access to parameter ss +#-----| -> foreach (... ... in ...) ... + +# 91| {...} +#-----| -> if (...) ... + +# 92| if (...) ... +#-----| -> access to local variable b + +# 92| access to local variable b +#-----| true -> ...; +#-----| false -> if (...) ... + +# 93| ...; +#-----| -> access to local variable x + +# 93| ...++ +#-----| -> if (...) ... + +# 93| access to local variable x +#-----| -> ...++ + +# 94| if (...) ... +#-----| -> access to local variable x + +# 94| ... > ... +#-----| true -> ...; +#-----| false -> if (...) ... + +# 94| access to local variable x +#-----| -> 0 + +# 94| 0 +#-----| -> ... > ... + +# 95| ...; +#-----| -> false + +# 95| ... = ... +#-----| -> if (...) ... + +# 95| false +#-----| -> ... = ... + +# 96| if (...) ... +#-----| -> access to local variable b + +# 96| access to local variable b +#-----| false -> foreach (... ... in ...) ... +#-----| true -> ...; + +# 97| ...; +#-----| -> access to local variable x + +# 97| ...++ +#-----| -> foreach (... ... in ...) ... + +# 97| access to local variable x +#-----| -> ...++ + +# 99| return ...; +#-----| return -> exit M7 (normal) + +# 99| access to local variable x +#-----| -> return ...; + +# 102| enter M8 +#-----| -> {...} + +# 102| exit M8 + +# 102| exit M8 (normal) +#-----| -> exit M8 + +# 103| {...} +#-----| -> ... ...; + +# 104| ... ...; +#-----| -> access to parameter b + +# 104| String x = ... +#-----| -> if (...) ... + +# 104| call to method ToString +#-----| -> String x = ... + +# 104| access to parameter b +#-----| -> call to method ToString + +# 105| if (...) ... +#-----| -> access to parameter b + +# 105| access to parameter b +#-----| true -> [b (line 102): true] ...; +#-----| false -> [b (line 102): false] if (...) ... + +# 106| [b (line 102): true] ...; +#-----| -> [b (line 102): true] access to local variable x + +# 106| [b (line 102): true] ... = ... +#-----| -> [b (line 102): true] if (...) ... + +# 106| [b (line 102): true] ... + ... +#-----| -> [b (line 102): true] ... = ... + +# 106| [b (line 102): true] access to local variable x +#-----| -> [b (line 102): true] "" + +# 106| [b (line 102): true] "" +#-----| -> [b (line 102): true] ... + ... + +# 107| [b (line 102): false] if (...) ... +#-----| -> [b (line 102): false] access to local variable x + +# 107| [b (line 102): true] if (...) ... +#-----| -> [b (line 102): true] access to local variable x + +# 107| [b (line 102): false] ... > ... +#-----| true -> [b (line 102): false] if (...) ... +#-----| false -> access to local variable x + +# 107| [b (line 102): true] ... > ... +#-----| true -> [b (line 102): true] if (...) ... +#-----| false -> access to local variable x + +# 107| [b (line 102): false] access to property Length +#-----| -> [b (line 102): false] 0 + +# 107| [b (line 102): true] access to property Length +#-----| -> [b (line 102): true] 0 + +# 107| [b (line 102): false] access to local variable x +#-----| -> [b (line 102): false] access to property Length + +# 107| [b (line 102): true] access to local variable x +#-----| -> [b (line 102): true] access to property Length + +# 107| [b (line 102): false] 0 +#-----| -> [b (line 102): false] ... > ... + +# 107| [b (line 102): true] 0 +#-----| -> [b (line 102): true] ... > ... + +# 108| [b (line 102): false] if (...) ... +#-----| -> [b (line 102): false] access to parameter b + +# 108| [b (line 102): true] if (...) ... +#-----| -> [b (line 102): true] access to parameter b + +# 108| [false] !... +#-----| false -> access to local variable x + +# 108| [true] !... +#-----| true -> ...; + +# 108| [b (line 102): false] access to parameter b +#-----| false -> [true] !... + +# 108| [b (line 102): true] access to parameter b +#-----| true -> [false] !... + +# 109| ...; +#-----| -> access to local variable x + +# 109| ... = ... +#-----| -> access to local variable x + +# 109| ... + ... +#-----| -> ... = ... + +# 109| access to local variable x +#-----| -> "" + +# 109| "" +#-----| -> ... + ... + +# 110| return ...; +#-----| return -> exit M8 (normal) + +# 110| access to local variable x +#-----| -> return ...; + +# 113| enter M9 +#-----| -> {...} + +# 113| exit M9 + +# 113| exit M9 (normal) +#-----| -> exit M9 + +# 114| {...} +#-----| -> ... ...; + +# 115| ... ...; +#-----| -> null + +# 115| String s = ... +#-----| -> for (...;...;...) ... + +# 115| null +#-----| -> String s = ... + +# 116| for (...;...;...) ... +#-----| -> 0 + +# 116| Int32 i = ... +#-----| -> access to local variable i + +# 116| 0 +#-----| -> Int32 i = ... + +# 116| ... < ... +#-----| true -> {...} +#-----| false -> exit M9 (normal) + +# 116| access to local variable i +#-----| -> access to parameter args + +# 116| access to property Length +#-----| -> ... < ... + +# 116| access to parameter args +#-----| -> access to property Length + +# 116| ...++ +#-----| -> access to local variable i + +# 116| access to local variable i +#-----| -> ...++ + +# 117| {...} +#-----| -> ... ...; + +# 118| ... ...; +#-----| -> access to local variable i + +# 118| Boolean last = ... +#-----| -> if (...) ... + +# 118| ... == ... +#-----| -> Boolean last = ... + +# 118| access to local variable i +#-----| -> access to parameter args + +# 118| ... - ... +#-----| -> ... == ... + +# 118| access to property Length +#-----| -> 1 + +# 118| access to parameter args +#-----| -> access to property Length + +# 118| 1 +#-----| -> ... - ... + +# 119| if (...) ... +#-----| -> access to local variable last + +# 119| [false, last (line 118): true] !... +#-----| false -> [last (line 118): true] if (...) ... + +# 119| [true, last (line 118): false] !... +#-----| true -> [last (line 118): false] ...; + +# 119| access to local variable last +#-----| true -> [false, last (line 118): true] !... +#-----| false -> [true, last (line 118): false] !... + +# 120| [last (line 118): false] ...; +#-----| -> [last (line 118): false] "" + +# 120| [last (line 118): false] ... = ... +#-----| -> [last (line 118): false] if (...) ... + +# 120| [last (line 118): false] "" +#-----| -> [last (line 118): false] ... = ... + +# 121| [last (line 118): false] if (...) ... +#-----| -> [last (line 118): false] access to local variable last + +# 121| [last (line 118): true] if (...) ... +#-----| -> [last (line 118): true] access to local variable last + +# 121| [last (line 118): false] access to local variable last +#-----| false -> access to local variable i + +# 121| [last (line 118): true] access to local variable last +#-----| true -> ...; + +# 122| ...; +#-----| -> null + +# 122| ... = ... +#-----| -> access to local variable i + +# 122| null +#-----| -> ... = ... + +# 129| enter M10 +#-----| -> {...} + +# 130| {...} +#-----| -> while (...) ... + +# 131| while (...) ... +#-----| -> true + +# 131| true +#-----| true -> {...} + +# 131| [Field1 (line 129): false] true +#-----| true -> [Field1 (line 129): false] {...} + +# 131| [Field1 (line 129): true, Field2 (line 129): false] true +#-----| true -> [Field1 (line 129): true, Field2 (line 129): false] {...} + +# 131| [Field1 (line 129): true, Field2 (line 129): true] true +#-----| true -> [Field1 (line 129): true, Field2 (line 129): true] {...} + +# 132| {...} +#-----| -> if (...) ... + +# 132| [Field1 (line 129): false] {...} +#-----| -> [Field1 (line 129): false] if (...) ... + +# 132| [Field1 (line 129): true, Field2 (line 129): false] {...} +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] if (...) ... + +# 132| [Field1 (line 129): true, Field2 (line 129): true] {...} +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] if (...) ... + +# 133| if (...) ... +#-----| -> this access + +# 133| [Field1 (line 129): false] if (...) ... +#-----| -> [Field1 (line 129): false] this access + +# 133| [Field1 (line 129): true, Field2 (line 129): false] if (...) ... +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] this access + +# 133| [Field1 (line 129): true, Field2 (line 129): true] if (...) ... +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] this access + +# 133| access to field Field1 +#-----| false -> [Field1 (line 129): false] true +#-----| true -> [Field1 (line 129): true] {...} + +# 133| [Field1 (line 129): false] access to field Field1 +#-----| false -> [Field1 (line 129): false] true + +# 133| [Field1 (line 129): true, Field2 (line 129): false] access to field Field1 +#-----| true -> [Field1 (line 129): true, Field2 (line 129): false] {...} + +# 133| [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 +#-----| true -> [Field1 (line 129): true, Field2 (line 129): true] {...} + +# 133| this access +#-----| -> access to field Field1 + +# 133| [Field1 (line 129): false] this access +#-----| -> [Field1 (line 129): false] access to field Field1 + +# 133| [Field1 (line 129): true, Field2 (line 129): false] this access +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] access to field Field1 + +# 133| [Field1 (line 129): true, Field2 (line 129): true] this access +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 + +# 134| [Field1 (line 129): true] {...} +#-----| -> [Field1 (line 129): true] if (...) ... + +# 134| [Field1 (line 129): true, Field2 (line 129): false] {...} +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] if (...) ... + +# 134| [Field1 (line 129): true, Field2 (line 129): true] {...} +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] if (...) ... + +# 135| [Field1 (line 129): true] if (...) ... +#-----| -> [Field1 (line 129): true] this access + +# 135| [Field1 (line 129): true, Field2 (line 129): false] if (...) ... +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] this access + +# 135| [Field1 (line 129): true, Field2 (line 129): true] if (...) ... +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] this access + +# 135| [Field1 (line 129): true] access to field Field2 +#-----| false -> [Field1 (line 129): true, Field2 (line 129): false] true +#-----| true -> [Field1 (line 129): true, Field2 (line 129): true] {...} + +# 135| [Field1 (line 129): true, Field2 (line 129): false] access to field Field2 +#-----| false -> [Field1 (line 129): true, Field2 (line 129): false] true + +# 135| [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 +#-----| true -> [Field1 (line 129): true, Field2 (line 129): true] {...} + +# 135| [Field1 (line 129): true] this access +#-----| -> [Field1 (line 129): true] access to field Field2 + +# 135| [Field1 (line 129): true, Field2 (line 129): false] this access +#-----| -> [Field1 (line 129): true, Field2 (line 129): false] access to field Field2 + +# 135| [Field1 (line 129): true, Field2 (line 129): true] this access +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] access to field Field2 + +# 136| [Field1 (line 129): true, Field2 (line 129): true] {...} +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] ...; + +# 137| [Field1 (line 129): true, Field2 (line 129): true] ...; +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] this access + +# 137| [Field1 (line 129): true, Field2 (line 129): true] call to method ToString +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] true + +# 137| [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] call to method ToString + +# 137| [Field1 (line 129): true, Field2 (line 129): true] this access +#-----| -> [Field1 (line 129): true, Field2 (line 129): true] access to field Field1 + +# 143| enter M11 +#-----| -> {...} + +# 143| exit M11 + +# 143| exit M11 (normal) +#-----| -> exit M11 + +# 144| {...} +#-----| -> ... ...; + +# 145| ... ...; +#-----| -> access to parameter b + +# 145| [b (line 143): false] String s = ... +#-----| -> [b (line 143): false] if (...) ... + +# 145| [b (line 143): true] String s = ... +#-----| -> [b (line 143): true] if (...) ... + +# 145| [b (line 143): false] ... ? ... : ... +#-----| -> [b (line 143): false] String s = ... + +# 145| [b (line 143): true] ... ? ... : ... +#-----| -> [b (line 143): true] String s = ... + +# 145| access to parameter b +#-----| true -> [b (line 143): true] "a" +#-----| false -> [b (line 143): false] "b" + +# 145| [b (line 143): true] "a" +#-----| -> [b (line 143): true] ... ? ... : ... + +# 145| [b (line 143): false] "b" +#-----| -> [b (line 143): false] ... ? ... : ... + +# 146| [b (line 143): false] if (...) ... +#-----| -> [b (line 143): false] access to parameter b + +# 146| [b (line 143): true] if (...) ... +#-----| -> [b (line 143): true] access to parameter b + +# 146| [b (line 143): false] access to parameter b +#-----| false -> ...; + +# 146| [b (line 143): true] access to parameter b +#-----| true -> ...; + +# 147| ...; +#-----| -> "a = " + +# 147| call to method WriteLine +#-----| -> exit M11 (normal) + +# 147| $"..." +#-----| -> call to method WriteLine + +# 147| "a = " +#-----| -> access to local variable s + +# 147| access to local variable s +#-----| -> $"..." + +# 149| ...; +#-----| -> "b = " + +# 149| call to method WriteLine +#-----| -> exit M11 (normal) + +# 149| $"..." +#-----| -> call to method WriteLine + +# 149| "b = " +#-----| -> access to local variable s + +# 149| access to local variable s +#-----| -> $"..." + +ExitMethods.cs: +# 8| enter M1 +#-----| -> {...} + +# 8| exit M1 + +# 8| exit M1 (normal) +#-----| -> exit M1 + +# 9| {...} +#-----| -> ...; + +# 10| ...; +#-----| -> true + +# 10| call to method ErrorMaybe +#-----| -> return ...; + +# 10| true +#-----| -> call to method ErrorMaybe + +# 11| return ...; +#-----| return -> exit M1 (normal) + +# 14| enter M2 +#-----| -> {...} + +# 14| exit M2 + +# 14| exit M2 (normal) +#-----| -> exit M2 + +# 15| {...} +#-----| -> ...; + +# 16| ...; +#-----| -> false + +# 16| call to method ErrorMaybe +#-----| -> return ...; + +# 16| false +#-----| -> call to method ErrorMaybe + +# 17| return ...; +#-----| return -> exit M2 (normal) + +# 20| enter M3 +#-----| -> {...} + +# 20| exit M3 + +# 20| exit M3 (abnormal) +#-----| -> exit M3 + +# 21| {...} +#-----| -> ...; + +# 22| ...; +#-----| -> true + +# 22| call to method ErrorAlways +#-----| exception(Exception) -> exit M3 (abnormal) + +# 22| true +#-----| -> call to method ErrorAlways + +# 26| enter M4 +#-----| -> {...} + +# 26| exit M4 + +# 26| exit M4 (abnormal) +#-----| -> exit M4 + +# 27| {...} +#-----| -> ...; + +# 28| ...; +#-----| -> this access + +# 28| call to method Exit +#-----| exit -> exit M4 (abnormal) + +# 28| this access +#-----| -> call to method Exit + +# 32| enter M5 +#-----| -> {...} + +# 32| exit M5 + +# 32| exit M5 (abnormal) +#-----| -> exit M5 + +# 33| {...} +#-----| -> ...; + +# 34| ...; +#-----| -> this access + +# 34| call to method ApplicationExit +#-----| exit -> exit M5 (abnormal) + +# 34| this access +#-----| -> call to method ApplicationExit + +# 38| enter M6 +#-----| -> {...} + +# 38| exit M6 + +# 38| exit M6 (normal) +#-----| -> exit M6 + +# 39| {...} +#-----| -> try {...} ... + +# 40| try {...} ... +#-----| -> {...} + +# 41| {...} +#-----| -> ...; + +# 42| ...; +#-----| -> false + +# 42| call to method ErrorAlways +#-----| exception(ArgumentException) -> [exception: ArgumentException] catch (...) {...} +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} + +# 42| false +#-----| -> call to method ErrorAlways + +# 44| [exception: ArgumentException] catch (...) {...} +#-----| match -> {...} + +# 44| [exception: Exception] catch (...) {...} +#-----| match -> {...} +#-----| no-match -> [exception: Exception] catch (...) {...} + +# 45| {...} +#-----| -> return ...; + +# 46| return ...; +#-----| return -> exit M6 (normal) + +# 48| [exception: Exception] catch (...) {...} +#-----| match -> {...} + +# 49| {...} +#-----| -> return ...; + +# 50| return ...; +#-----| return -> exit M6 (normal) + +# 54| enter M7 +#-----| -> {...} + +# 54| exit M7 + +# 54| exit M7 (abnormal) +#-----| -> exit M7 + +# 55| {...} +#-----| -> ...; + +# 56| ...; +#-----| -> call to method ErrorAlways2 + +# 56| call to method ErrorAlways2 +#-----| exception(Exception) -> exit M7 (abnormal) + +# 60| enter M8 +#-----| -> {...} + +# 60| exit M8 + +# 60| exit M8 (abnormal) +#-----| -> exit M8 + +# 61| {...} +#-----| -> ...; + +# 62| ...; +#-----| -> call to method ErrorAlways3 + +# 62| call to method ErrorAlways3 +#-----| exception(Exception) -> exit M8 (abnormal) + +# 66| enter ErrorMaybe +#-----| -> {...} + +# 66| exit ErrorMaybe + +# 66| exit ErrorMaybe (abnormal) +#-----| -> exit ErrorMaybe + +# 66| exit ErrorMaybe (normal) +#-----| -> exit ErrorMaybe + +# 67| {...} +#-----| -> if (...) ... + +# 68| if (...) ... +#-----| -> access to parameter b + +# 68| access to parameter b +#-----| true -> object creation of type Exception +#-----| false -> exit ErrorMaybe (normal) + +# 69| throw ...; +#-----| exception(Exception) -> exit ErrorMaybe (abnormal) + +# 69| object creation of type Exception +#-----| -> throw ...; + +# 72| enter ErrorAlways +#-----| -> {...} + +# 72| exit ErrorAlways + +# 72| exit ErrorAlways (abnormal) +#-----| -> exit ErrorAlways + +# 73| {...} +#-----| -> if (...) ... + +# 74| if (...) ... +#-----| -> access to parameter b + +# 74| access to parameter b +#-----| true -> object creation of type Exception +#-----| false -> "b" + +# 75| throw ...; +#-----| exception(Exception) -> exit ErrorAlways (abnormal) + +# 75| object creation of type Exception +#-----| -> throw ...; + +# 77| throw ...; +#-----| exception(ArgumentException) -> exit ErrorAlways (abnormal) + +# 77| object creation of type ArgumentException +#-----| -> throw ...; + +# 77| "b" +#-----| -> object creation of type ArgumentException + +# 80| enter ErrorAlways2 +#-----| -> {...} + +# 80| exit ErrorAlways2 + +# 80| exit ErrorAlways2 (abnormal) +#-----| -> exit ErrorAlways2 + +# 81| {...} +#-----| -> object creation of type Exception + +# 82| throw ...; +#-----| exception(Exception) -> exit ErrorAlways2 (abnormal) + +# 82| object creation of type Exception +#-----| -> throw ...; + +# 85| enter ErrorAlways3 +#-----| -> object creation of type Exception + +# 85| exit ErrorAlways3 + +# 85| exit ErrorAlways3 (abnormal) +#-----| -> exit ErrorAlways3 + +# 85| throw ... +#-----| exception(Exception) -> exit ErrorAlways3 (abnormal) + +# 85| object creation of type Exception +#-----| -> throw ... + +# 87| enter Exit +#-----| -> {...} + +# 87| exit Exit + +# 87| exit Exit (abnormal) +#-----| -> exit Exit + +# 88| {...} +#-----| -> ...; + +# 89| ...; +#-----| -> 0 + +# 89| call to method Exit +#-----| exit -> exit Exit (abnormal) + +# 89| 0 +#-----| -> call to method Exit + +# 92| enter ExitInTry +#-----| -> {...} + +# 92| exit ExitInTry + +# 92| exit ExitInTry (abnormal) +#-----| -> exit ExitInTry + +# 93| {...} +#-----| -> try {...} ... + +# 94| try {...} ... +#-----| -> {...} + +# 95| {...} +#-----| -> ...; + +# 96| ...; +#-----| -> this access + +# 96| call to method Exit +#-----| exit -> exit ExitInTry (abnormal) + +# 96| this access +#-----| -> call to method Exit + +# 105| enter ApplicationExit +#-----| -> {...} + +# 105| exit ApplicationExit + +# 105| exit ApplicationExit (abnormal) +#-----| -> exit ApplicationExit + +# 106| {...} +#-----| -> ...; + +# 107| ...; +#-----| -> call to method Exit + +# 107| call to method Exit +#-----| exit -> exit ApplicationExit (abnormal) + +# 110| enter ThrowExpr +#-----| -> {...} + +# 110| exit ThrowExpr + +# 110| exit ThrowExpr (abnormal) +#-----| -> exit ThrowExpr + +# 110| exit ThrowExpr (normal) +#-----| -> exit ThrowExpr + +# 111| {...} +#-----| -> access to parameter input + +# 112| return ...; +#-----| return -> exit ThrowExpr (normal) + +# 112| ... ? ... : ... +#-----| -> return ...; + +# 112| ... != ... +#-----| false -> "input" +#-----| true -> 1 + +# 112| access to parameter input +#-----| -> 0 + +# 112| (...) ... +#-----| -> ... != ... + +# 112| 0 +#-----| -> (...) ... + +# 112| ... / ... +#-----| -> ... ? ... : ... + +# 112| (...) ... +#-----| -> access to parameter input + +# 112| 1 +#-----| -> (...) ... + +# 112| access to parameter input +#-----| -> ... / ... + +# 112| throw ... +#-----| exception(ArgumentException) -> exit ThrowExpr (abnormal) + +# 112| object creation of type ArgumentException +#-----| -> throw ... + +# 112| "input" +#-----| -> object creation of type ArgumentException + +# 115| enter ExtensionMethodCall +#-----| -> {...} + +# 115| exit ExtensionMethodCall + +# 115| exit ExtensionMethodCall (normal) +#-----| -> exit ExtensionMethodCall + +# 116| {...} +#-----| -> access to parameter s + +# 117| return ...; +#-----| return -> exit ExtensionMethodCall (normal) + +# 117| ... ? ... : ... +#-----| -> return ...; + +# 117| call to method Contains +#-----| true -> 0 +#-----| false -> 1 + +# 117| access to parameter s +#-----| -> - + +# 117| - +#-----| -> call to method Contains + +# 117| 0 +#-----| -> ... ? ... : ... + +# 117| 1 +#-----| -> ... ? ... : ... + +# 120| enter FailingAssertion +#-----| -> {...} + +# 120| exit FailingAssertion + +# 120| exit FailingAssertion (abnormal) +#-----| -> exit FailingAssertion + +# 121| {...} +#-----| -> ...; + +# 122| ...; +#-----| -> false + +# 122| [assertion failure] call to method IsTrue +#-----| exception(AssertFailedException) -> exit FailingAssertion (abnormal) + +# 122| false +#-----| false -> [assertion failure] call to method IsTrue + +# 126| enter FailingAssertion2 +#-----| -> {...} + +# 126| exit FailingAssertion2 + +# 126| exit FailingAssertion2 (abnormal) +#-----| -> exit FailingAssertion2 + +# 127| {...} +#-----| -> ...; + +# 128| ...; +#-----| -> this access + +# 128| call to method FailingAssertion +#-----| exception(AssertFailedException) -> exit FailingAssertion2 (abnormal) + +# 128| this access +#-----| -> call to method FailingAssertion + +# 132| enter AssertFalse +#-----| -> access to parameter b + +# 132| exit AssertFalse + +# 132| exit AssertFalse (abnormal) +#-----| -> exit AssertFalse + +# 132| exit AssertFalse (normal) +#-----| -> exit AssertFalse + +# 132| [assertion failure] call to method IsFalse +#-----| exception(AssertFailedException) -> exit AssertFalse (abnormal) + +# 132| [assertion success] call to method IsFalse +#-----| -> exit AssertFalse (normal) + +# 132| access to parameter b +#-----| true -> [assertion failure] call to method IsFalse +#-----| false -> [assertion success] call to method IsFalse + +# 134| enter FailingAssertion3 +#-----| -> {...} + +# 134| exit FailingAssertion3 + +# 134| exit FailingAssertion3 (abnormal) +#-----| -> exit FailingAssertion3 + +# 135| {...} +#-----| -> ...; + +# 136| ...; +#-----| -> this access + +# 136| [assertion failure] call to method AssertFalse +#-----| exception(AssertFailedException) -> exit FailingAssertion3 (abnormal) + +# 136| this access +#-----| -> true + +# 136| true +#-----| true -> [assertion failure] call to method AssertFalse + +# 140| enter ExceptionDispatchInfoThrow +#-----| -> {...} + +# 140| exit ExceptionDispatchInfoThrow + +# 140| exit ExceptionDispatchInfoThrow (abnormal) +#-----| -> exit ExceptionDispatchInfoThrow + +# 141| {...} +#-----| -> if (...) ... + +# 142| if (...) ... +#-----| -> access to parameter b + +# 142| access to parameter b +#-----| true -> ...; +#-----| false -> ...; + +# 143| ...; +#-----| -> access to parameter e + +# 143| call to method Throw +#-----| exception(ArgumentException) -> exit ExceptionDispatchInfoThrow (abnormal) + +# 143| access to parameter e +#-----| -> call to method Throw + +# 145| ...; +#-----| -> access to parameter e + +# 145| call to method Throw +#-----| exception(Exception) -> exit ExceptionDispatchInfoThrow (abnormal) + +# 145| call to method Capture +#-----| -> call to method Throw + +# 145| access to parameter e +#-----| -> call to method Capture + +Extensions.cs: +# 5| enter ToInt32 +#-----| -> {...} + +# 5| exit ToInt32 + +# 5| exit ToInt32 (normal) +#-----| -> exit ToInt32 + +# 6| {...} +#-----| -> access to parameter s + +# 7| return ...; +#-----| return -> exit ToInt32 (normal) + +# 7| call to method Parse +#-----| -> return ...; + +# 7| access to parameter s +#-----| -> call to method Parse + +# 10| enter ToBool +#-----| -> {...} + +# 10| exit ToBool + +# 10| exit ToBool (normal) +#-----| -> exit ToBool + +# 11| {...} +#-----| -> access to parameter f + +# 12| return ...; +#-----| return -> exit ToBool (normal) + +# 12| delegate call +#-----| -> return ...; + +# 12| access to parameter f +#-----| -> access to parameter s + +# 12| access to parameter s +#-----| -> delegate call + +# 15| enter CallToInt32 +#-----| -> "0" + +# 15| exit CallToInt32 + +# 15| exit CallToInt32 (normal) +#-----| -> exit CallToInt32 + +# 15| call to method ToInt32 +#-----| -> exit CallToInt32 (normal) + +# 15| "0" +#-----| -> call to method ToInt32 + +# 20| enter Main +#-----| -> {...} + +# 20| exit Main + +# 20| exit Main (normal) +#-----| -> exit Main + +# 21| {...} +#-----| -> ...; + +# 22| ...; +#-----| -> access to parameter s + +# 22| call to method ToInt32 +#-----| -> ...; + +# 22| access to parameter s +#-----| -> call to method ToInt32 + +# 23| ...; +#-----| -> "" + +# 23| call to method ToInt32 +#-----| -> ...; + +# 23| "" +#-----| -> call to method ToInt32 + +# 24| ...; +#-----| -> "true" + +# 24| call to method ToBool +#-----| -> ...; + +# 24| "true" +#-----| -> access to method Parse + +# 24| delegate creation of type Func +#-----| -> call to method ToBool + +# 24| access to method Parse +#-----| -> delegate creation of type Func + +# 25| ...; +#-----| -> "true" + +# 25| call to method ToBool +#-----| -> exit Main (normal) + +# 25| "true" +#-----| -> access to method Parse + +# 25| delegate creation of type Func +#-----| -> call to method ToBool + +# 25| access to method Parse +#-----| -> delegate creation of type Func + +Finally.cs: +# 7| enter M1 +#-----| -> {...} + +# 7| exit M1 + +# 7| exit M1 (abnormal) +#-----| -> exit M1 + +# 7| exit M1 (normal) +#-----| -> exit M1 + +# 8| {...} +#-----| -> try {...} ... + +# 9| try {...} ... +#-----| -> {...} + +# 10| {...} +#-----| -> ...; + +# 11| ...; +#-----| -> "Try1" + +# 11| call to method WriteLine +#-----| -> {...} +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 11| "Try1" +#-----| -> call to method WriteLine + +# 14| {...} +#-----| -> ...; + +# 14| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 15| ...; +#-----| -> "Finally" + +# 15| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "Finally" + +# 15| call to method WriteLine +#-----| -> exit M1 (normal) + +# 15| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M1 (abnormal) + +# 15| "Finally" +#-----| -> call to method WriteLine + +# 15| [finally: exception(Exception)] "Finally" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 19| enter M2 +#-----| -> {...} + +# 19| exit M2 + +# 19| exit M2 (abnormal) +#-----| -> exit M2 + +# 19| exit M2 (normal) +#-----| -> exit M2 + +# 20| {...} +#-----| -> try {...} ... + +# 21| try {...} ... +#-----| -> {...} + +# 22| {...} +#-----| -> ...; + +# 23| ...; +#-----| -> "Try2" + +# 23| call to method WriteLine +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} +#-----| -> return ...; + +# 23| "Try2" +#-----| -> call to method WriteLine + +# 24| return ...; +#-----| return -> [finally: return] {...} + +# 26| [exception: Exception] catch (...) {...} +#-----| match -> [exception: Exception] IOException ex +#-----| no-match -> [exception: Exception] catch (...) {...} + +# 26| [exception: Exception] IOException ex +#-----| -> [exception: Exception] true + +# 26| [exception: Exception] true +#-----| true -> {...} + +# 27| {...} +#-----| -> throw ...; + +# 28| throw ...; +#-----| exception(IOException) -> [finally: exception(IOException)] {...} + +# 30| [exception: Exception] catch (...) {...} +#-----| match -> [exception: Exception] ArgumentException ex +#-----| no-match -> [exception: Exception] catch (...) {...} + +# 30| [exception: Exception] ArgumentException ex +#-----| -> {...} + +# 31| {...} +#-----| -> try {...} ... + +# 32| try {...} ... +#-----| -> {...} + +# 33| {...} +#-----| -> if (...) ... + +# 34| if (...) ... +#-----| -> true + +# 34| true +#-----| true -> throw ...; + +# 34| throw ...; +#-----| exception(ArgumentException) -> [finally: exception(ArgumentException)] {...} + +# 37| [finally: exception(ArgumentException)] {...} +#-----| -> [finally: exception(ArgumentException)] "Boo!" + +# 38| [finally: exception(ArgumentException)] throw ...; +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 38| [finally: exception(ArgumentException)] object creation of type Exception +#-----| -> [finally: exception(ArgumentException)] throw ...; + +# 38| [finally: exception(ArgumentException)] "Boo!" +#-----| -> [finally: exception(ArgumentException)] object creation of type Exception + +# 41| [exception: Exception] catch (...) {...} +#-----| match -> {...} + +# 42| {...} +#-----| -> {...} + +# 49| {...} +#-----| -> ...; + +# 49| [finally: return] {...} +#-----| -> [finally: return] ...; + +# 49| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 49| [finally: exception(IOException)] {...} +#-----| -> [finally: exception(IOException)] ...; + +# 50| ...; +#-----| -> "Finally" + +# 50| [finally: return] ...; +#-----| -> [finally: return] "Finally" + +# 50| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "Finally" + +# 50| [finally: exception(IOException)] ...; +#-----| -> [finally: exception(IOException)] "Finally" + +# 50| call to method WriteLine +#-----| -> exit M2 (normal) + +# 50| [finally: return] call to method WriteLine +#-----| return -> exit M2 (normal) + +# 50| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M2 (abnormal) + +# 50| [finally: exception(IOException)] call to method WriteLine +#-----| exception(IOException) -> exit M2 (abnormal) + +# 50| "Finally" +#-----| -> call to method WriteLine + +# 50| [finally: return] "Finally" +#-----| -> [finally: return] call to method WriteLine + +# 50| [finally: exception(Exception)] "Finally" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 50| [finally: exception(IOException)] "Finally" +#-----| -> [finally: exception(IOException)] call to method WriteLine + +# 54| enter M3 +#-----| -> {...} + +# 54| exit M3 + +# 54| exit M3 (abnormal) +#-----| -> exit M3 + +# 54| exit M3 (normal) +#-----| -> exit M3 + +# 55| {...} +#-----| -> try {...} ... + +# 56| try {...} ... +#-----| -> {...} + +# 57| {...} +#-----| -> ...; + +# 58| ...; +#-----| -> "Try3" + +# 58| call to method WriteLine +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} +#-----| -> return ...; + +# 58| "Try3" +#-----| -> call to method WriteLine + +# 59| return ...; +#-----| return -> [finally: return] {...} + +# 61| [exception: Exception] catch (...) {...} +#-----| match -> [exception: Exception] IOException ex +#-----| no-match -> [exception: Exception] catch (...) {...} + +# 61| [exception: Exception] IOException ex +#-----| -> [exception: Exception] true + +# 61| [exception: Exception] true +#-----| true -> {...} + +# 62| {...} +#-----| -> throw ...; + +# 63| throw ...; +#-----| exception(IOException) -> [finally: exception(IOException)] {...} + +# 65| [exception: Exception] catch (...) {...} +#-----| match -> [exception: Exception] Exception e + +# 65| [exception: Exception] Exception e +#-----| -> [exception: Exception] access to local variable e + +# 65| [exception: Exception] ... != ... +#-----| true -> {...} +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 65| [exception: Exception] access to property Message +#-----| -> [exception: Exception] null + +# 65| [exception: Exception] access to local variable e +#-----| -> [exception: Exception] access to property Message + +# 65| [exception: Exception] null +#-----| -> [exception: Exception] ... != ... + +# 66| {...} +#-----| -> {...} + +# 69| {...} +#-----| -> ...; + +# 69| [finally: return] {...} +#-----| -> [finally: return] ...; + +# 69| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 69| [finally: exception(IOException)] {...} +#-----| -> [finally: exception(IOException)] ...; + +# 70| ...; +#-----| -> "Finally" + +# 70| [finally: return] ...; +#-----| -> [finally: return] "Finally" + +# 70| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "Finally" + +# 70| [finally: exception(IOException)] ...; +#-----| -> [finally: exception(IOException)] "Finally" + +# 70| call to method WriteLine +#-----| -> exit M3 (normal) + +# 70| [finally: return] call to method WriteLine +#-----| return -> exit M3 (normal) + +# 70| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M3 (abnormal) + +# 70| [finally: exception(IOException)] call to method WriteLine +#-----| exception(IOException) -> exit M3 (abnormal) + +# 70| "Finally" +#-----| -> call to method WriteLine + +# 70| [finally: return] "Finally" +#-----| -> [finally: return] call to method WriteLine + +# 70| [finally: exception(Exception)] "Finally" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 70| [finally: exception(IOException)] "Finally" +#-----| -> [finally: exception(IOException)] call to method WriteLine + +# 74| enter M4 +#-----| -> {...} + +# 74| exit M4 + +# 74| exit M4 (abnormal) +#-----| -> exit M4 + +# 74| exit M4 (normal) +#-----| -> exit M4 + +# 75| {...} +#-----| -> ... ...; + +# 76| ... ...; +#-----| -> 10 + +# 76| Int32 i = ... +#-----| -> while (...) ... + +# 76| 10 +#-----| -> Int32 i = ... + +# 77| while (...) ... +#-----| -> access to local variable i + +# 77| ... > ... +#-----| true -> {...} +#-----| false -> exit M4 (normal) + +# 77| access to local variable i +#-----| -> 0 + +# 77| 0 +#-----| -> ... > ... + +# 78| {...} +#-----| -> try {...} ... + +# 79| try {...} ... +#-----| -> {...} + +# 80| {...} +#-----| -> if (...) ... + +# 81| if (...) ... +#-----| -> access to local variable i + +# 81| ... == ... +#-----| true -> return ...; +#-----| false -> if (...) ... + +# 81| access to local variable i +#-----| -> 0 + +# 81| 0 +#-----| -> ... == ... + +# 82| return ...; +#-----| return -> [finally: return] {...} + +# 83| if (...) ... +#-----| -> access to local variable i + +# 83| ... == ... +#-----| true -> continue; +#-----| false -> if (...) ... + +# 83| access to local variable i +#-----| -> 1 + +# 83| 1 +#-----| -> ... == ... + +# 84| continue; +#-----| continue -> [finally: continue] {...} + +# 85| if (...) ... +#-----| -> access to local variable i + +# 85| ... == ... +#-----| true -> break; +#-----| false -> {...} + +# 85| access to local variable i +#-----| -> 2 + +# 85| 2 +#-----| -> ... == ... + +# 86| break; +#-----| break -> [finally: break] {...} + +# 89| {...} +#-----| -> try {...} ... + +# 89| [finally: return] {...} +#-----| -> [finally: return] try {...} ... + +# 89| [finally: break] {...} +#-----| -> [finally: break] try {...} ... + +# 89| [finally: continue] {...} +#-----| -> [finally: continue] try {...} ... + +# 90| try {...} ... +#-----| -> {...} + +# 90| [finally: return] try {...} ... +#-----| -> [finally: return] {...} + +# 90| [finally: break] try {...} ... +#-----| -> [finally: break] {...} + +# 90| [finally: continue] try {...} ... +#-----| -> [finally: continue] {...} + +# 91| {...} +#-----| -> if (...) ... + +# 91| [finally: return] {...} +#-----| -> [finally: return] if (...) ... + +# 91| [finally: break] {...} +#-----| -> [finally: break] if (...) ... + +# 91| [finally: continue] {...} +#-----| -> [finally: continue] if (...) ... + +# 92| if (...) ... +#-----| -> access to local variable i + +# 92| [finally: return] if (...) ... +#-----| -> [finally: return] access to local variable i + +# 92| [finally: break] if (...) ... +#-----| -> [finally: break] access to local variable i + +# 92| [finally: continue] if (...) ... +#-----| -> [finally: continue] access to local variable i + +# 92| ... == ... +#-----| true -> object creation of type Exception +#-----| false -> {...} + +# 92| [finally: return] ... == ... +#-----| true -> [finally: return] object creation of type Exception +#-----| false -> [finally: return] {...} + +# 92| [finally: break] ... == ... +#-----| true -> [finally: break] object creation of type Exception +#-----| false -> [finally: break] {...} + +# 92| [finally: continue] ... == ... +#-----| true -> [finally: continue] object creation of type Exception +#-----| false -> [finally: continue] {...} + +# 92| access to local variable i +#-----| -> 3 + +# 92| [finally: return] access to local variable i +#-----| -> [finally: return] 3 + +# 92| [finally: break] access to local variable i +#-----| -> [finally: break] 3 + +# 92| [finally: continue] access to local variable i +#-----| -> [finally: continue] 3 + +# 92| 3 +#-----| -> ... == ... + +# 92| [finally: return] 3 +#-----| -> [finally: return] ... == ... + +# 92| [finally: break] 3 +#-----| -> [finally: break] ... == ... + +# 92| [finally: continue] 3 +#-----| -> [finally: continue] ... == ... + +# 93| throw ...; +#-----| exception(Exception) -> [finally(1): exception(Exception)] {...} + +# 93| [finally: return] throw ...; +#-----| exception(Exception) -> [finally: return, finally(1): exception(Exception)] {...} + +# 93| [finally: break] throw ...; +#-----| exception(Exception) -> [finally: break, finally(1): exception(Exception)] {...} + +# 93| [finally: continue] throw ...; +#-----| exception(Exception) -> [finally: continue, finally(1): exception(Exception)] {...} + +# 93| object creation of type Exception +#-----| -> throw ...; +#-----| exception(Exception) -> [finally(1): exception(Exception)] {...} + +# 93| [finally: return] object creation of type Exception +#-----| -> [finally: return] throw ...; +#-----| exception(Exception) -> [finally: return, finally(1): exception(Exception)] {...} + +# 93| [finally: break] object creation of type Exception +#-----| -> [finally: break] throw ...; +#-----| exception(Exception) -> [finally: break, finally(1): exception(Exception)] {...} + +# 93| [finally: continue] object creation of type Exception +#-----| -> [finally: continue] throw ...; +#-----| exception(Exception) -> [finally: continue, finally(1): exception(Exception)] {...} + +# 96| {...} +#-----| -> ...; + +# 96| [finally(1): exception(Exception)] {...} +#-----| -> [finally(1): exception(Exception)] ...; + +# 96| [finally: return] {...} +#-----| -> [finally: return] ...; + +# 96| [finally: return, finally(1): exception(Exception)] {...} +#-----| -> [finally: return, finally(1): exception(Exception)] ...; + +# 96| [finally: break] {...} +#-----| -> [finally: break] ...; + +# 96| [finally: break, finally(1): exception(Exception)] {...} +#-----| -> [finally: break, finally(1): exception(Exception)] ...; + +# 96| [finally: continue] {...} +#-----| -> [finally: continue] ...; + +# 96| [finally: continue, finally(1): exception(Exception)] {...} +#-----| -> [finally: continue, finally(1): exception(Exception)] ...; + +# 97| ...; +#-----| -> access to local variable i + +# 97| [finally(1): exception(Exception)] ...; +#-----| -> [finally(1): exception(Exception)] access to local variable i + +# 97| [finally: return] ...; +#-----| -> [finally: return] access to local variable i + +# 97| [finally: return, finally(1): exception(Exception)] ...; +#-----| -> [finally: return, finally(1): exception(Exception)] access to local variable i + +# 97| [finally: break] ...; +#-----| -> [finally: break] access to local variable i + +# 97| [finally: break, finally(1): exception(Exception)] ...; +#-----| -> [finally: break, finally(1): exception(Exception)] access to local variable i + +# 97| [finally: continue] ...; +#-----| -> [finally: continue] access to local variable i + +# 97| [finally: continue, finally(1): exception(Exception)] ...; +#-----| -> [finally: continue, finally(1): exception(Exception)] access to local variable i + +# 97| ...-- +#-----| -> access to local variable i + +# 97| [finally(1): exception(Exception)] ...-- +#-----| exception(Exception) -> exit M4 (abnormal) + +# 97| [finally: return] ...-- +#-----| return -> exit M4 (normal) + +# 97| [finally: return, finally(1): exception(Exception)] ...-- +#-----| exception(Exception) -> exit M4 (abnormal) + +# 97| [finally: break] ...-- +#-----| break -> exit M4 (normal) + +# 97| [finally: break, finally(1): exception(Exception)] ...-- +#-----| exception(Exception) -> exit M4 (abnormal) + +# 97| [finally: continue] ...-- +#-----| continue -> access to local variable i + +# 97| [finally: continue, finally(1): exception(Exception)] ...-- +#-----| exception(Exception) -> exit M4 (abnormal) + +# 97| access to local variable i +#-----| -> ...-- + +# 97| [finally(1): exception(Exception)] access to local variable i +#-----| -> [finally(1): exception(Exception)] ...-- + +# 97| [finally: return] access to local variable i +#-----| -> [finally: return] ...-- + +# 97| [finally: return, finally(1): exception(Exception)] access to local variable i +#-----| -> [finally: return, finally(1): exception(Exception)] ...-- + +# 97| [finally: break] access to local variable i +#-----| -> [finally: break] ...-- + +# 97| [finally: break, finally(1): exception(Exception)] access to local variable i +#-----| -> [finally: break, finally(1): exception(Exception)] ...-- + +# 97| [finally: continue] access to local variable i +#-----| -> [finally: continue] ...-- + +# 97| [finally: continue, finally(1): exception(Exception)] access to local variable i +#-----| -> [finally: continue, finally(1): exception(Exception)] ...-- + +# 103| enter M5 +#-----| -> {...} + +# 103| exit M5 + +# 103| exit M5 (abnormal) +#-----| -> exit M5 + +# 103| exit M5 (normal) +#-----| -> exit M5 + +# 104| {...} +#-----| -> try {...} ... + +# 105| try {...} ... +#-----| -> {...} + +# 106| {...} +#-----| -> if (...) ... + +# 107| if (...) ... +#-----| -> this access + +# 107| ... == ... +#-----| true -> return ...; +#-----| false -> if (...) ... + +# 107| access to property Length +#-----| exception(Exception) -> [finally: exception(Exception)] {...} +#-----| exception(NullReferenceException) -> [finally: exception(NullReferenceException)] {...} +#-----| -> 0 + +# 107| access to field Field +#-----| exception(NullReferenceException) -> [finally: exception(NullReferenceException)] {...} +#-----| -> access to property Length + +# 107| this access +#-----| -> access to field Field + +# 107| 0 +#-----| -> ... == ... + +# 108| return ...; +#-----| return -> [finally: return] {...} + +# 109| if (...) ... +#-----| -> this access + +# 109| ... == ... +#-----| true -> object creation of type OutOfMemoryException +#-----| false -> {...} + +# 109| access to property Length +#-----| exception(Exception) -> [finally: exception(Exception)] {...} +#-----| exception(NullReferenceException) -> [finally: exception(NullReferenceException)] {...} +#-----| -> 1 + +# 109| access to field Field +#-----| exception(NullReferenceException) -> [finally: exception(NullReferenceException)] {...} +#-----| -> access to property Length + +# 109| this access +#-----| -> access to field Field + +# 109| 1 +#-----| -> ... == ... + +# 110| throw ...; +#-----| exception(OutOfMemoryException) -> [finally: exception(OutOfMemoryException)] {...} + +# 110| object creation of type OutOfMemoryException +#-----| -> throw ...; +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 113| {...} +#-----| -> if (...) ... + +# 113| [finally: return] {...} +#-----| -> [finally: return] if (...) ... + +# 113| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] if (...) ... + +# 113| [finally: exception(OutOfMemoryException)] {...} +#-----| -> [finally: exception(OutOfMemoryException)] if (...) ... + +# 113| [finally: exception(NullReferenceException)] {...} +#-----| -> [finally: exception(NullReferenceException)] if (...) ... + +# 114| if (...) ... +#-----| -> this access + +# 114| [finally: return] if (...) ... +#-----| -> [finally: return] this access + +# 114| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] this access + +# 114| [finally: exception(OutOfMemoryException)] if (...) ... +#-----| -> [finally: exception(OutOfMemoryException)] this access + +# 114| [finally: exception(NullReferenceException)] if (...) ... +#-----| -> [finally: exception(NullReferenceException)] this access + +# 114| [false] !... +#-----| false -> if (...) ... + +# 114| [false, finally: return] !... +#-----| false -> [finally: return] if (...) ... + +# 114| [false, finally: exception(Exception)] !... +#-----| false -> [finally: exception(Exception)] if (...) ... + +# 114| [false, finally: exception(OutOfMemoryException)] !... +#-----| false -> [finally: exception(OutOfMemoryException)] if (...) ... + +# 114| [false, finally: exception(NullReferenceException)] !... +#-----| false -> [finally: exception(NullReferenceException)] if (...) ... + +# 114| [true] !... +#-----| true -> ...; + +# 114| [true, finally: return] !... +#-----| true -> [finally: return] ...; + +# 114| [true, finally: exception(Exception)] !... +#-----| true -> [finally: exception(Exception)] ...; + +# 114| [true, finally: exception(OutOfMemoryException)] !... +#-----| true -> [finally: exception(OutOfMemoryException)] ...; + +# 114| [true, finally: exception(NullReferenceException)] !... +#-----| true -> [finally: exception(NullReferenceException)] ...; + +# 114| ... == ... +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 114| [finally: return] ... == ... +#-----| true -> [false, finally: return] !... +#-----| false -> [true, finally: return] !... + +# 114| [finally: exception(Exception)] ... == ... +#-----| true -> [false, finally: exception(Exception)] !... +#-----| false -> [true, finally: exception(Exception)] !... + +# 114| [finally: exception(OutOfMemoryException)] ... == ... +#-----| true -> [false, finally: exception(OutOfMemoryException)] !... +#-----| false -> [true, finally: exception(OutOfMemoryException)] !... + +# 114| [finally: exception(NullReferenceException)] ... == ... +#-----| true -> [false, finally: exception(NullReferenceException)] !... +#-----| false -> [true, finally: exception(NullReferenceException)] !... + +# 114| access to property Length +#-----| -> 0 + +# 114| [finally: return] access to property Length +#-----| -> [finally: return] 0 + +# 114| [finally: exception(Exception)] access to property Length +#-----| -> [finally: exception(Exception)] 0 + +# 114| [finally: exception(OutOfMemoryException)] access to property Length +#-----| -> [finally: exception(OutOfMemoryException)] 0 + +# 114| [finally: exception(NullReferenceException)] access to property Length +#-----| -> [finally: exception(NullReferenceException)] 0 + +# 114| access to field Field +#-----| -> access to property Length + +# 114| [finally: return] access to field Field +#-----| -> [finally: return] access to property Length + +# 114| [finally: exception(Exception)] access to field Field +#-----| -> [finally: exception(Exception)] access to property Length + +# 114| [finally: exception(OutOfMemoryException)] access to field Field +#-----| -> [finally: exception(OutOfMemoryException)] access to property Length + +# 114| [finally: exception(NullReferenceException)] access to field Field +#-----| -> [finally: exception(NullReferenceException)] access to property Length + +# 114| this access +#-----| -> access to field Field + +# 114| [finally: return] this access +#-----| -> [finally: return] access to field Field + +# 114| [finally: exception(Exception)] this access +#-----| -> [finally: exception(Exception)] access to field Field + +# 114| [finally: exception(OutOfMemoryException)] this access +#-----| -> [finally: exception(OutOfMemoryException)] access to field Field + +# 114| [finally: exception(NullReferenceException)] this access +#-----| -> [finally: exception(NullReferenceException)] access to field Field + +# 114| 0 +#-----| -> ... == ... + +# 114| [finally: return] 0 +#-----| -> [finally: return] ... == ... + +# 114| [finally: exception(Exception)] 0 +#-----| -> [finally: exception(Exception)] ... == ... + +# 114| [finally: exception(OutOfMemoryException)] 0 +#-----| -> [finally: exception(OutOfMemoryException)] ... == ... + +# 114| [finally: exception(NullReferenceException)] 0 +#-----| -> [finally: exception(NullReferenceException)] ... == ... + +# 115| ...; +#-----| -> this access + +# 115| [finally: return] ...; +#-----| -> [finally: return] this access + +# 115| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] this access + +# 115| [finally: exception(OutOfMemoryException)] ...; +#-----| -> [finally: exception(OutOfMemoryException)] this access + +# 115| [finally: exception(NullReferenceException)] ...; +#-----| -> [finally: exception(NullReferenceException)] this access + +# 115| call to method WriteLine +#-----| -> if (...) ... + +# 115| [finally: return] call to method WriteLine +#-----| -> [finally: return] if (...) ... + +# 115| [finally: exception(Exception)] call to method WriteLine +#-----| -> [finally: exception(Exception)] if (...) ... + +# 115| [finally: exception(OutOfMemoryException)] call to method WriteLine +#-----| -> [finally: exception(OutOfMemoryException)] if (...) ... + +# 115| [finally: exception(NullReferenceException)] call to method WriteLine +#-----| -> [finally: exception(NullReferenceException)] if (...) ... + +# 115| access to field Field +#-----| -> call to method WriteLine + +# 115| [finally: return] access to field Field +#-----| -> [finally: return] call to method WriteLine + +# 115| [finally: exception(Exception)] access to field Field +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 115| [finally: exception(OutOfMemoryException)] access to field Field +#-----| -> [finally: exception(OutOfMemoryException)] call to method WriteLine + +# 115| [finally: exception(NullReferenceException)] access to field Field +#-----| -> [finally: exception(NullReferenceException)] call to method WriteLine + +# 115| this access +#-----| -> access to field Field + +# 115| [finally: return] this access +#-----| -> [finally: return] access to field Field + +# 115| [finally: exception(Exception)] this access +#-----| -> [finally: exception(Exception)] access to field Field + +# 115| [finally: exception(OutOfMemoryException)] this access +#-----| -> [finally: exception(OutOfMemoryException)] access to field Field + +# 115| [finally: exception(NullReferenceException)] this access +#-----| -> [finally: exception(NullReferenceException)] access to field Field + +# 116| if (...) ... +#-----| -> this access + +# 116| [finally: return] if (...) ... +#-----| -> [finally: return] this access + +# 116| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] this access + +# 116| [finally: exception(OutOfMemoryException)] if (...) ... +#-----| -> [finally: exception(OutOfMemoryException)] this access + +# 116| [finally: exception(NullReferenceException)] if (...) ... +#-----| -> [finally: exception(NullReferenceException)] this access + +# 116| ... > ... +#-----| true -> ...; +#-----| false -> exit M5 (normal) + +# 116| [finally: return] ... > ... +#-----| true -> [finally: return] ...; +#-----| return -> exit M5 (normal) + +# 116| [finally: exception(Exception)] ... > ... +#-----| true -> [finally: exception(Exception)] ...; +#-----| exception(Exception) -> exit M5 (abnormal) + +# 116| [finally: exception(OutOfMemoryException)] ... > ... +#-----| true -> [finally: exception(OutOfMemoryException)] ...; +#-----| exception(OutOfMemoryException) -> exit M5 (abnormal) + +# 116| [finally: exception(NullReferenceException)] ... > ... +#-----| true -> [finally: exception(NullReferenceException)] ...; +#-----| exception(NullReferenceException) -> exit M5 (abnormal) + +# 116| access to property Length +#-----| -> 0 + +# 116| [finally: return] access to property Length +#-----| -> [finally: return] 0 + +# 116| [finally: exception(Exception)] access to property Length +#-----| -> [finally: exception(Exception)] 0 + +# 116| [finally: exception(OutOfMemoryException)] access to property Length +#-----| -> [finally: exception(OutOfMemoryException)] 0 + +# 116| [finally: exception(NullReferenceException)] access to property Length +#-----| -> [finally: exception(NullReferenceException)] 0 + +# 116| access to field Field +#-----| -> access to property Length + +# 116| [finally: return] access to field Field +#-----| -> [finally: return] access to property Length + +# 116| [finally: exception(Exception)] access to field Field +#-----| -> [finally: exception(Exception)] access to property Length + +# 116| [finally: exception(OutOfMemoryException)] access to field Field +#-----| -> [finally: exception(OutOfMemoryException)] access to property Length + +# 116| [finally: exception(NullReferenceException)] access to field Field +#-----| -> [finally: exception(NullReferenceException)] access to property Length + +# 116| this access +#-----| -> access to field Field + +# 116| [finally: return] this access +#-----| -> [finally: return] access to field Field + +# 116| [finally: exception(Exception)] this access +#-----| -> [finally: exception(Exception)] access to field Field + +# 116| [finally: exception(OutOfMemoryException)] this access +#-----| -> [finally: exception(OutOfMemoryException)] access to field Field + +# 116| [finally: exception(NullReferenceException)] this access +#-----| -> [finally: exception(NullReferenceException)] access to field Field + +# 116| 0 +#-----| -> ... > ... + +# 116| [finally: return] 0 +#-----| -> [finally: return] ... > ... + +# 116| [finally: exception(Exception)] 0 +#-----| -> [finally: exception(Exception)] ... > ... + +# 116| [finally: exception(OutOfMemoryException)] 0 +#-----| -> [finally: exception(OutOfMemoryException)] ... > ... + +# 116| [finally: exception(NullReferenceException)] 0 +#-----| -> [finally: exception(NullReferenceException)] ... > ... + +# 117| ...; +#-----| -> 1 + +# 117| [finally: return] ...; +#-----| -> [finally: return] 1 + +# 117| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] 1 + +# 117| [finally: exception(OutOfMemoryException)] ...; +#-----| -> [finally: exception(OutOfMemoryException)] 1 + +# 117| [finally: exception(NullReferenceException)] ...; +#-----| -> [finally: exception(NullReferenceException)] 1 + +# 117| call to method WriteLine +#-----| -> exit M5 (normal) + +# 117| [finally: return] call to method WriteLine +#-----| return -> exit M5 (normal) + +# 117| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M5 (abnormal) + +# 117| [finally: exception(OutOfMemoryException)] call to method WriteLine +#-----| exception(OutOfMemoryException) -> exit M5 (abnormal) + +# 117| [finally: exception(NullReferenceException)] call to method WriteLine +#-----| exception(NullReferenceException) -> exit M5 (abnormal) + +# 117| 1 +#-----| -> call to method WriteLine + +# 117| [finally: return] 1 +#-----| -> [finally: return] call to method WriteLine + +# 117| [finally: exception(Exception)] 1 +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 117| [finally: exception(OutOfMemoryException)] 1 +#-----| -> [finally: exception(OutOfMemoryException)] call to method WriteLine + +# 117| [finally: exception(NullReferenceException)] 1 +#-----| -> [finally: exception(NullReferenceException)] call to method WriteLine + +# 121| enter M6 +#-----| -> {...} + +# 121| exit M6 + +# 121| exit M6 (normal) +#-----| -> exit M6 + +# 122| {...} +#-----| -> try {...} ... + +# 123| try {...} ... +#-----| -> {...} + +# 124| {...} +#-----| -> ... ...; + +# 125| ... ...; +#-----| -> 0 + +# 125| Double temp = ... +#-----| -> exit M6 (normal) + +# 125| ... / ... +#-----| -> Double temp = ... + +# 125| (...) ... +#-----| -> access to constant E + +# 125| 0 +#-----| -> (...) ... + +# 125| access to constant E +#-----| -> ... / ... + +# 133| enter M7 +#-----| -> {...} + +# 133| exit M7 + +# 133| exit M7 (abnormal) +#-----| -> exit M7 + +# 134| {...} +#-----| -> try {...} ... + +# 135| try {...} ... +#-----| -> {...} + +# 136| {...} +#-----| -> ...; + +# 137| ...; +#-----| -> "Try" + +# 137| call to method WriteLine +#-----| -> {...} +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 137| "Try" +#-----| -> call to method WriteLine + +# 140| {...} +#-----| -> "" + +# 140| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] "" + +# 141| throw ...; +#-----| exception(ArgumentException) -> exit M7 (abnormal) + +# 141| [finally: exception(Exception)] throw ...; +#-----| exception(ArgumentException) -> exit M7 (abnormal) + +# 141| object creation of type ArgumentException +#-----| -> throw ...; + +# 141| [finally: exception(Exception)] object creation of type ArgumentException +#-----| -> [finally: exception(Exception)] throw ...; + +# 141| "" +#-----| -> object creation of type ArgumentException + +# 141| [finally: exception(Exception)] "" +#-----| -> [finally: exception(Exception)] object creation of type ArgumentException + +# 147| enter M8 +#-----| -> {...} + +# 147| exit M8 + +# 147| exit M8 (abnormal) +#-----| -> exit M8 + +# 147| exit M8 (normal) +#-----| -> exit M8 + +# 148| {...} +#-----| -> try {...} ... + +# 149| try {...} ... +#-----| -> {...} + +# 150| {...} +#-----| -> if (...) ... + +# 151| if (...) ... +#-----| -> access to parameter args + +# 151| ... == ... +#-----| true -> object creation of type ArgumentNullException +#-----| false -> {...} + +# 151| access to parameter args +#-----| -> null + +# 151| null +#-----| -> ... == ... + +# 152| throw ...; +#-----| exception(ArgumentNullException) -> [finally: exception(ArgumentNullException)] {...} + +# 152| object creation of type ArgumentNullException +#-----| -> throw ...; +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 155| {...} +#-----| -> try {...} ... + +# 155| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] try {...} ... + +# 155| [finally: exception(ArgumentNullException)] {...} +#-----| -> [finally: exception(ArgumentNullException)] try {...} ... + +# 156| try {...} ... +#-----| -> {...} + +# 156| [finally: exception(Exception)] try {...} ... +#-----| -> [finally: exception(Exception)] {...} + +# 156| [finally: exception(ArgumentNullException)] try {...} ... +#-----| -> [finally: exception(ArgumentNullException)] {...} + +# 157| {...} +#-----| -> if (...) ... + +# 157| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] if (...) ... + +# 157| [finally: exception(ArgumentNullException)] {...} +#-----| -> [finally: exception(ArgumentNullException)] if (...) ... + +# 158| if (...) ... +#-----| -> access to parameter args + +# 158| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] access to parameter args + +# 158| [finally: exception(ArgumentNullException)] if (...) ... +#-----| -> [finally: exception(ArgumentNullException)] access to parameter args + +# 158| ... == ... +#-----| true -> "1" +#-----| false -> exit M8 (normal) + +# 158| [finally: exception(Exception)] ... == ... +#-----| true -> [finally: exception(Exception)] "1" +#-----| exception(Exception) -> exit M8 (abnormal) + +# 158| [finally: exception(ArgumentNullException)] ... == ... +#-----| true -> [finally: exception(ArgumentNullException)] "1" +#-----| exception(ArgumentNullException) -> exit M8 (abnormal) + +# 158| access to property Length +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} +#-----| exception(NullReferenceException) -> [exception: NullReferenceException] catch (...) {...} +#-----| -> 1 + +# 158| [finally: exception(Exception)] access to property Length +#-----| exception(Exception) -> [finally: exception(Exception), exception: Exception] catch (...) {...} +#-----| exception(NullReferenceException) -> [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} +#-----| -> [finally: exception(Exception)] 1 + +# 158| [finally: exception(ArgumentNullException)] access to property Length +#-----| exception(Exception) -> [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} +#-----| exception(NullReferenceException) -> [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} +#-----| -> [finally: exception(ArgumentNullException)] 1 + +# 158| access to parameter args +#-----| -> access to property Length + +# 158| [finally: exception(Exception)] access to parameter args +#-----| -> [finally: exception(Exception)] access to property Length + +# 158| [finally: exception(ArgumentNullException)] access to parameter args +#-----| -> [finally: exception(ArgumentNullException)] access to property Length + +# 158| 1 +#-----| -> ... == ... + +# 158| [finally: exception(Exception)] 1 +#-----| -> [finally: exception(Exception)] ... == ... + +# 158| [finally: exception(ArgumentNullException)] 1 +#-----| -> [finally: exception(ArgumentNullException)] ... == ... + +# 159| throw ...; +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} + +# 159| [finally: exception(Exception)] throw ...; +#-----| exception(Exception) -> [finally: exception(Exception), exception: Exception] catch (...) {...} + +# 159| [finally: exception(ArgumentNullException)] throw ...; +#-----| exception(Exception) -> [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} + +# 159| object creation of type Exception +#-----| exception(Exception) -> [exception: Exception] catch (...) {...} +#-----| -> throw ...; + +# 159| [finally: exception(Exception)] object creation of type Exception +#-----| exception(Exception) -> [finally: exception(Exception), exception: Exception] catch (...) {...} +#-----| -> [finally: exception(Exception)] throw ...; + +# 159| [finally: exception(ArgumentNullException)] object creation of type Exception +#-----| exception(Exception) -> [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} +#-----| -> [finally: exception(ArgumentNullException)] throw ...; + +# 159| "1" +#-----| -> object creation of type Exception + +# 159| [finally: exception(Exception)] "1" +#-----| -> [finally: exception(Exception)] object creation of type Exception + +# 159| [finally: exception(ArgumentNullException)] "1" +#-----| -> [finally: exception(ArgumentNullException)] object creation of type Exception + +# 161| [exception: Exception] catch (...) {...} +#-----| match -> [exception: Exception] Exception e + +# 161| [finally: exception(Exception), exception: Exception] catch (...) {...} +#-----| match -> [finally: exception(Exception), exception: Exception] Exception e + +# 161| [finally: exception(ArgumentNullException), exception: Exception] catch (...) {...} +#-----| match -> [finally: exception(ArgumentNullException), exception: Exception] Exception e + +# 161| [exception: NullReferenceException] catch (...) {...} +#-----| match -> [exception: NullReferenceException] Exception e + +# 161| [finally: exception(Exception), exception: NullReferenceException] catch (...) {...} +#-----| match -> [finally: exception(Exception), exception: NullReferenceException] Exception e + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] catch (...) {...} +#-----| match -> [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e + +# 161| [exception: Exception] Exception e +#-----| -> [exception: Exception] access to local variable e + +# 161| [finally: exception(Exception), exception: Exception] Exception e +#-----| -> [finally: exception(Exception), exception: Exception] access to local variable e + +# 161| [finally: exception(ArgumentNullException), exception: Exception] Exception e +#-----| -> [finally: exception(ArgumentNullException), exception: Exception] access to local variable e + +# 161| [exception: NullReferenceException] Exception e +#-----| -> [exception: NullReferenceException] access to local variable e + +# 161| [finally: exception(Exception), exception: NullReferenceException] Exception e +#-----| -> [finally: exception(Exception), exception: NullReferenceException] access to local variable e + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] Exception e +#-----| -> [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e + +# 161| [exception: Exception] ... == ... +#-----| true -> {...} +#-----| false -> catch {...} + +# 161| [finally: exception(Exception), exception: Exception] ... == ... +#-----| true -> [finally: exception(Exception)] {...} +#-----| false -> [finally: exception(Exception)] catch {...} + +# 161| [finally: exception(ArgumentNullException), exception: Exception] ... == ... +#-----| true -> [finally: exception(ArgumentNullException)] {...} +#-----| false -> [finally: exception(ArgumentNullException)] catch {...} + +# 161| [exception: NullReferenceException] ... == ... +#-----| true -> {...} +#-----| false -> catch {...} + +# 161| [finally: exception(Exception), exception: NullReferenceException] ... == ... +#-----| true -> [finally: exception(Exception)] {...} +#-----| false -> [finally: exception(Exception)] catch {...} + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... +#-----| true -> [finally: exception(ArgumentNullException)] {...} +#-----| false -> [finally: exception(ArgumentNullException)] catch {...} + +# 161| [exception: Exception] access to property Message +#-----| -> [exception: Exception] "1" + +# 161| [finally: exception(Exception), exception: Exception] access to property Message +#-----| -> [finally: exception(Exception), exception: Exception] "1" + +# 161| [finally: exception(ArgumentNullException), exception: Exception] access to property Message +#-----| -> [finally: exception(ArgumentNullException), exception: Exception] "1" + +# 161| [exception: NullReferenceException] access to property Message +#-----| -> [exception: NullReferenceException] "1" + +# 161| [finally: exception(Exception), exception: NullReferenceException] access to property Message +#-----| -> [finally: exception(Exception), exception: NullReferenceException] "1" + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message +#-----| -> [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" + +# 161| [exception: Exception] access to local variable e +#-----| -> [exception: Exception] access to property Message + +# 161| [finally: exception(Exception), exception: Exception] access to local variable e +#-----| -> [finally: exception(Exception), exception: Exception] access to property Message + +# 161| [finally: exception(ArgumentNullException), exception: Exception] access to local variable e +#-----| -> [finally: exception(ArgumentNullException), exception: Exception] access to property Message + +# 161| [exception: NullReferenceException] access to local variable e +#-----| -> [exception: NullReferenceException] access to property Message + +# 161| [finally: exception(Exception), exception: NullReferenceException] access to local variable e +#-----| -> [finally: exception(Exception), exception: NullReferenceException] access to property Message + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] access to local variable e +#-----| -> [finally: exception(ArgumentNullException), exception: NullReferenceException] access to property Message + +# 161| [exception: Exception] "1" +#-----| -> [exception: Exception] ... == ... + +# 161| [finally: exception(Exception), exception: Exception] "1" +#-----| -> [finally: exception(Exception), exception: Exception] ... == ... + +# 161| [finally: exception(ArgumentNullException), exception: Exception] "1" +#-----| -> [finally: exception(ArgumentNullException), exception: Exception] ... == ... + +# 161| [exception: NullReferenceException] "1" +#-----| -> [exception: NullReferenceException] ... == ... + +# 161| [finally: exception(Exception), exception: NullReferenceException] "1" +#-----| -> [finally: exception(Exception), exception: NullReferenceException] ... == ... + +# 161| [finally: exception(ArgumentNullException), exception: NullReferenceException] "1" +#-----| -> [finally: exception(ArgumentNullException), exception: NullReferenceException] ... == ... + +# 162| {...} +#-----| -> ...; + +# 162| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 162| [finally: exception(ArgumentNullException)] {...} +#-----| -> [finally: exception(ArgumentNullException)] ...; + +# 163| ...; +#-----| -> access to parameter args + +# 163| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] access to parameter args + +# 163| [finally: exception(ArgumentNullException)] ...; +#-----| -> [finally: exception(ArgumentNullException)] access to parameter args + +# 163| call to method WriteLine +#-----| -> exit M8 (normal) + +# 163| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M8 (abnormal) + +# 163| [finally: exception(ArgumentNullException)] call to method WriteLine +#-----| exception(ArgumentNullException) -> exit M8 (abnormal) + +# 163| access to array element +#-----| -> call to method WriteLine + +# 163| [finally: exception(Exception)] access to array element +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 163| [finally: exception(ArgumentNullException)] access to array element +#-----| -> [finally: exception(ArgumentNullException)] call to method WriteLine + +# 163| access to parameter args +#-----| -> 0 + +# 163| [finally: exception(Exception)] access to parameter args +#-----| -> [finally: exception(Exception)] 0 + +# 163| [finally: exception(ArgumentNullException)] access to parameter args +#-----| -> [finally: exception(ArgumentNullException)] 0 + +# 163| 0 +#-----| -> access to array element + +# 163| [finally: exception(Exception)] 0 +#-----| -> [finally: exception(Exception)] access to array element + +# 163| [finally: exception(ArgumentNullException)] 0 +#-----| -> [finally: exception(ArgumentNullException)] access to array element + +# 165| catch {...} +#-----| -> {...} + +# 165| [finally: exception(Exception)] catch {...} +#-----| -> [finally: exception(Exception)] {...} + +# 165| [finally: exception(ArgumentNullException)] catch {...} +#-----| -> [finally: exception(ArgumentNullException)] {...} + +# 166| {...} +#-----| -> ...; + +# 166| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 166| [finally: exception(ArgumentNullException)] {...} +#-----| -> [finally: exception(ArgumentNullException)] ...; + +# 167| ...; +#-----| -> "" + +# 167| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "" + +# 167| [finally: exception(ArgumentNullException)] ...; +#-----| -> [finally: exception(ArgumentNullException)] "" + +# 167| call to method WriteLine +#-----| -> exit M8 (normal) + +# 167| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M8 (abnormal) + +# 167| [finally: exception(ArgumentNullException)] call to method WriteLine +#-----| exception(ArgumentNullException) -> exit M8 (abnormal) + +# 167| "" +#-----| -> call to method WriteLine + +# 167| [finally: exception(Exception)] "" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 167| [finally: exception(ArgumentNullException)] "" +#-----| -> [finally: exception(ArgumentNullException)] call to method WriteLine + +# 176| enter M9 +#-----| -> {...} + +# 176| exit M9 + +# 176| exit M9 (abnormal) +#-----| -> exit M9 + +# 176| exit M9 (normal) +#-----| -> exit M9 + +# 177| {...} +#-----| -> try {...} ... + +# 178| try {...} ... +#-----| -> {...} + +# 179| {...} +#-----| -> if (...) ... + +# 180| if (...) ... +#-----| -> access to parameter b1 + +# 180| access to parameter b1 +#-----| true -> [b1 (line 176): true] object creation of type ExceptionA +#-----| false -> [b1 (line 176): false] {...} + +# 180| [b1 (line 176): true] throw ...; +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA), b1 (line 176): true] {...} + +# 180| [b1 (line 176): true] object creation of type ExceptionA +#-----| -> [b1 (line 176): true] throw ...; +#-----| exception(Exception) -> [finally: exception(Exception), b1 (line 176): true] {...} + +# 183| [b1 (line 176): false] {...} +#-----| -> [b1 (line 176): false] try {...} ... + +# 183| [finally: exception(Exception), b1 (line 176): true] {...} +#-----| -> [finally: exception(Exception), b1 (line 176): true] try {...} ... + +# 183| [finally: exception(ExceptionA), b1 (line 176): true] {...} +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] try {...} ... + +# 184| [b1 (line 176): false] try {...} ... +#-----| -> [b1 (line 176): false] {...} + +# 184| [finally: exception(Exception), b1 (line 176): true] try {...} ... +#-----| -> [finally: exception(Exception), b1 (line 176): true] {...} + +# 184| [finally: exception(ExceptionA), b1 (line 176): true] try {...} ... +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] {...} + +# 185| [b1 (line 176): false] {...} +#-----| -> [b1 (line 176): false] if (...) ... + +# 185| [finally: exception(Exception), b1 (line 176): true] {...} +#-----| -> [finally: exception(Exception), b1 (line 176): true] if (...) ... + +# 185| [finally: exception(ExceptionA), b1 (line 176): true] {...} +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... + +# 186| [b1 (line 176): false] if (...) ... +#-----| -> [b1 (line 176): false] access to parameter b2 + +# 186| [finally: exception(Exception), b1 (line 176): true] if (...) ... +#-----| -> [finally: exception(Exception), b1 (line 176): true] access to parameter b2 + +# 186| [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b2 + +# 186| [b1 (line 176): false] access to parameter b2 +#-----| true -> [b1 (line 176): false, b2 (line 176): true] object creation of type ExceptionB +#-----| false -> exit M9 (normal) + +# 186| [finally: exception(Exception), b1 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB +#-----| exception(Exception) -> exit M9 (abnormal) + +# 186| [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB +#-----| exception(ExceptionA) -> exit M9 (abnormal) + +# 186| [b1 (line 176): false, b2 (line 176): true] throw ...; +#-----| exception(ExceptionB) -> [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] catch (...) {...} + +# 186| [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] throw ...; +#-----| exception(ExceptionB) -> [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} + +# 186| [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] throw ...; +#-----| exception(ExceptionB) -> [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} + +# 186| [b1 (line 176): false, b2 (line 176): true] object creation of type ExceptionB +#-----| exception(Exception) -> [exception: Exception, b1 (line 176): false, b2 (line 176): true] catch (...) {...} +#-----| -> [b1 (line 176): false, b2 (line 176): true] throw ...; + +# 186| [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB +#-----| exception(Exception) -> [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| -> [finally: exception(Exception), b1 (line 176): true, b2 (line 176): true] throw ...; + +# 186| [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] object creation of type ExceptionB +#-----| exception(Exception) -> [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true, b2 (line 176): true] throw ...; + +# 188| [exception: Exception, b1 (line 176): false, b2 (line 176): true] catch (...) {...} +#-----| match -> [exception: Exception, b1 (line 176): false, b2 (line 176): true] access to parameter b2 +#-----| exception(Exception) -> exit M9 (abnormal) + +# 188| [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] catch (...) {...} +#-----| match -> [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] access to parameter b2 + +# 188| [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| match -> [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| exception(Exception) -> exit M9 (abnormal) + +# 188| [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| match -> [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 + +# 188| [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| match -> [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| exception(Exception) -> exit M9 (abnormal) + +# 188| [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] catch (...) {...} +#-----| match -> [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 + +# 188| [exception: Exception, b1 (line 176): false, b2 (line 176): true] access to parameter b2 +#-----| true -> [b1 (line 176): false] {...} + +# 188| [exception: ExceptionB, b1 (line 176): false, b2 (line 176): true] access to parameter b2 +#-----| true -> [b1 (line 176): false] {...} + +# 188| [finally: exception(Exception), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(Exception), b1 (line 176): true] {...} + +# 188| [finally: exception(Exception), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(Exception), b1 (line 176): true] {...} + +# 188| [finally: exception(ExceptionA), exception: Exception, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(ExceptionA), b1 (line 176): true] {...} + +# 188| [finally: exception(ExceptionA), exception: ExceptionB, b1 (line 176): true, b2 (line 176): true] access to parameter b2 +#-----| true -> [finally: exception(ExceptionA), b1 (line 176): true] {...} + +# 189| [b1 (line 176): false] {...} +#-----| -> [b1 (line 176): false] if (...) ... + +# 189| [finally: exception(Exception), b1 (line 176): true] {...} +#-----| -> [finally: exception(Exception), b1 (line 176): true] if (...) ... + +# 189| [finally: exception(ExceptionA), b1 (line 176): true] {...} +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... + +# 190| [b1 (line 176): false] if (...) ... +#-----| -> [b1 (line 176): false] access to parameter b1 + +# 190| [finally: exception(Exception), b1 (line 176): true] if (...) ... +#-----| -> [finally: exception(Exception), b1 (line 176): true] access to parameter b1 + +# 190| [finally: exception(ExceptionA), b1 (line 176): true] if (...) ... +#-----| -> [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b1 + +# 190| [b1 (line 176): false] access to parameter b1 +#-----| false -> exit M9 (normal) + +# 190| [finally: exception(Exception), b1 (line 176): true] access to parameter b1 +#-----| true -> [finally: exception(Exception)] object creation of type ExceptionC + +# 190| [finally: exception(ExceptionA), b1 (line 176): true] access to parameter b1 +#-----| true -> [finally: exception(ExceptionA)] object creation of type ExceptionC + +# 190| [finally: exception(Exception)] throw ...; +#-----| exception(ExceptionC) -> exit M9 (abnormal) + +# 190| [finally: exception(ExceptionA)] throw ...; +#-----| exception(ExceptionC) -> exit M9 (abnormal) + +# 190| [finally: exception(Exception)] object creation of type ExceptionC +#-----| -> [finally: exception(Exception)] throw ...; + +# 190| [finally: exception(ExceptionA)] object creation of type ExceptionC +#-----| -> [finally: exception(ExceptionA)] throw ...; + +# 195| enter M10 +#-----| -> {...} + +# 195| exit M10 + +# 195| exit M10 (abnormal) +#-----| -> exit M10 + +# 195| exit M10 (normal) +#-----| -> exit M10 + +# 196| {...} +#-----| -> try {...} ... + +# 197| try {...} ... +#-----| -> {...} + +# 198| {...} +#-----| -> if (...) ... + +# 199| if (...) ... +#-----| -> access to parameter b1 + +# 199| access to parameter b1 +#-----| true -> object creation of type ExceptionA +#-----| false -> {...} + +# 199| throw ...; +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 199| object creation of type ExceptionA +#-----| -> throw ...; +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 202| {...} +#-----| -> try {...} ... + +# 202| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] try {...} ... + +# 202| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] try {...} ... + +# 203| try {...} ... +#-----| -> {...} + +# 203| [finally: exception(Exception)] try {...} ... +#-----| -> [finally: exception(Exception)] {...} + +# 203| [finally: exception(ExceptionA)] try {...} ... +#-----| -> [finally: exception(ExceptionA)] {...} + +# 204| {...} +#-----| -> if (...) ... + +# 204| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] if (...) ... + +# 204| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] if (...) ... + +# 205| if (...) ... +#-----| -> access to parameter b2 + +# 205| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] access to parameter b2 + +# 205| [finally: exception(ExceptionA)] if (...) ... +#-----| -> [finally: exception(ExceptionA)] access to parameter b2 + +# 205| access to parameter b2 +#-----| true -> object creation of type ExceptionB +#-----| false -> {...} + +# 205| [finally: exception(Exception)] access to parameter b2 +#-----| true -> [finally: exception(Exception)] object creation of type ExceptionB +#-----| false -> [finally: exception(Exception)] {...} + +# 205| [finally: exception(ExceptionA)] access to parameter b2 +#-----| true -> [finally: exception(ExceptionA)] object creation of type ExceptionB +#-----| false -> [finally: exception(ExceptionA)] {...} + +# 205| throw ...; +#-----| exception(ExceptionB) -> [finally(1): exception(ExceptionB)] {...} + +# 205| [finally: exception(Exception)] throw ...; +#-----| exception(ExceptionB) -> [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} + +# 205| [finally: exception(ExceptionA)] throw ...; +#-----| exception(ExceptionB) -> [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} + +# 205| object creation of type ExceptionB +#-----| -> throw ...; +#-----| exception(Exception) -> [finally(1): exception(Exception)] {...} + +# 205| [finally: exception(Exception)] object creation of type ExceptionB +#-----| -> [finally: exception(Exception)] throw ...; +#-----| exception(Exception) -> [finally: exception(Exception), finally(1): exception(Exception)] {...} + +# 205| [finally: exception(ExceptionA)] object creation of type ExceptionB +#-----| -> [finally: exception(ExceptionA)] throw ...; +#-----| exception(Exception) -> [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} + +# 208| {...} +#-----| -> if (...) ... + +# 208| [finally(1): exception(Exception)] {...} +#-----| -> [finally(1): exception(Exception)] if (...) ... + +# 208| [finally(1): exception(ExceptionB)] {...} +#-----| -> [finally(1): exception(ExceptionB)] if (...) ... + +# 208| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] if (...) ... + +# 208| [finally: exception(Exception), finally(1): exception(Exception)] {...} +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... + +# 208| [finally: exception(Exception), finally(1): exception(ExceptionB)] {...} +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... + +# 208| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] if (...) ... + +# 208| [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... + +# 208| [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] {...} +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... + +# 209| if (...) ... +#-----| -> access to parameter b3 + +# 209| [finally(1): exception(Exception)] if (...) ... +#-----| -> [finally(1): exception(Exception)] access to parameter b3 + +# 209| [finally(1): exception(ExceptionB)] if (...) ... +#-----| -> [finally(1): exception(ExceptionB)] access to parameter b3 + +# 209| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] access to parameter b3 + +# 209| [finally: exception(Exception), finally(1): exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 + +# 209| [finally: exception(Exception), finally(1): exception(ExceptionB)] if (...) ... +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 + +# 209| [finally: exception(ExceptionA)] if (...) ... +#-----| -> [finally: exception(ExceptionA)] access to parameter b3 + +# 209| [finally: exception(ExceptionA), finally(1): exception(Exception)] if (...) ... +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 + +# 209| [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] if (...) ... +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 + +# 209| access to parameter b3 +#-----| true -> object creation of type ExceptionC +#-----| false -> ...; + +# 209| [finally(1): exception(Exception)] access to parameter b3 +#-----| true -> [finally(1): exception(Exception)] object creation of type ExceptionC +#-----| exception(Exception) -> exit M10 (abnormal) + +# 209| [finally(1): exception(ExceptionB)] access to parameter b3 +#-----| true -> [finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| exception(ExceptionB) -> exit M10 (abnormal) + +# 209| [finally: exception(Exception)] access to parameter b3 +#-----| true -> [finally: exception(Exception)] object creation of type ExceptionC +#-----| false -> [finally: exception(Exception)] ...; + +# 209| [finally: exception(Exception), finally(1): exception(Exception)] access to parameter b3 +#-----| true -> [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC +#-----| exception(Exception) -> exit M10 (abnormal) + +# 209| [finally: exception(Exception), finally(1): exception(ExceptionB)] access to parameter b3 +#-----| true -> [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| exception(ExceptionB) -> exit M10 (abnormal) + +# 209| [finally: exception(ExceptionA)] access to parameter b3 +#-----| true -> [finally: exception(ExceptionA)] object creation of type ExceptionC +#-----| false -> [finally: exception(ExceptionA)] ...; + +# 209| [finally: exception(ExceptionA), finally(1): exception(Exception)] access to parameter b3 +#-----| true -> [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC +#-----| exception(Exception) -> exit M10 (abnormal) + +# 209| [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] access to parameter b3 +#-----| true -> [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| exception(ExceptionB) -> exit M10 (abnormal) + +# 209| throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally(1): exception(Exception)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally(1): exception(ExceptionB)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(Exception)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(Exception), finally(1): exception(Exception)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(ExceptionA)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; +#-----| exception(ExceptionC) -> exit M10 (abnormal) + +# 209| object creation of type ExceptionC +#-----| -> throw ...; + +# 209| [finally(1): exception(Exception)] object creation of type ExceptionC +#-----| -> [finally(1): exception(Exception)] throw ...; + +# 209| [finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| -> [finally(1): exception(ExceptionB)] throw ...; + +# 209| [finally: exception(Exception)] object creation of type ExceptionC +#-----| -> [finally: exception(Exception)] throw ...; + +# 209| [finally: exception(Exception), finally(1): exception(Exception)] object creation of type ExceptionC +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] throw ...; + +# 209| [finally: exception(Exception), finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionB)] throw ...; + +# 209| [finally: exception(ExceptionA)] object creation of type ExceptionC +#-----| -> [finally: exception(ExceptionA)] throw ...; + +# 209| [finally: exception(ExceptionA), finally(1): exception(Exception)] object creation of type ExceptionC +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] throw ...; + +# 209| [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] object creation of type ExceptionC +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionB)] throw ...; + +# 211| ...; +#-----| -> this access + +# 211| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] this access + +# 211| [finally: exception(ExceptionA)] ...; +#-----| -> [finally: exception(ExceptionA)] this access + +# 211| ... = ... +#-----| -> ...; + +# 211| [finally: exception(Exception)] ... = ... +#-----| exception(Exception) -> exit M10 (abnormal) + +# 211| [finally: exception(ExceptionA)] ... = ... +#-----| exception(ExceptionA) -> exit M10 (abnormal) + +# 211| this access +#-----| -> "0" + +# 211| [finally: exception(Exception)] this access +#-----| -> [finally: exception(Exception)] "0" + +# 211| [finally: exception(ExceptionA)] this access +#-----| -> [finally: exception(ExceptionA)] "0" + +# 211| "0" +#-----| -> ... = ... + +# 211| [finally: exception(Exception)] "0" +#-----| -> [finally: exception(Exception)] ... = ... + +# 211| [finally: exception(ExceptionA)] "0" +#-----| -> [finally: exception(ExceptionA)] ... = ... + +# 213| ...; +#-----| -> this access + +# 213| ... = ... +#-----| -> exit M10 (normal) + +# 213| this access +#-----| -> "1" + +# 213| "1" +#-----| -> ... = ... + +# 216| enter M11 +#-----| -> {...} + +# 216| exit M11 + +# 216| exit M11 (normal) +#-----| -> exit M11 + +# 217| {...} +#-----| -> try {...} ... + +# 218| try {...} ... +#-----| -> {...} + +# 219| {...} +#-----| -> ...; + +# 220| ...; +#-----| -> "Try" + +# 220| call to method WriteLine +#-----| exception(Exception) -> catch {...} +#-----| -> {...} + +# 220| "Try" +#-----| -> call to method WriteLine + +# 222| catch {...} +#-----| -> {...} + +# 223| {...} +#-----| -> ...; + +# 224| ...; +#-----| -> "Catch" + +# 224| call to method WriteLine +#-----| -> {...} + +# 224| "Catch" +#-----| -> call to method WriteLine + +# 227| {...} +#-----| -> ...; + +# 228| ...; +#-----| -> "Finally" + +# 228| call to method WriteLine +#-----| -> ...; + +# 228| "Finally" +#-----| -> call to method WriteLine + +# 230| ...; +#-----| -> "Done" + +# 230| call to method WriteLine +#-----| -> exit M11 (normal) + +# 230| "Done" +#-----| -> call to method WriteLine + +# 233| enter M12 +#-----| -> {...} + +# 233| exit M12 + +# 233| exit M12 (abnormal) +#-----| -> exit M12 + +# 233| exit M12 (normal) +#-----| -> exit M12 + +# 234| {...} +#-----| -> try {...} ... + +# 235| try {...} ... +#-----| -> {...} + +# 236| {...} +#-----| -> try {...} ... + +# 237| try {...} ... +#-----| -> {...} + +# 238| {...} +#-----| -> if (...) ... + +# 239| if (...) ... +#-----| -> access to parameter b1 + +# 239| access to parameter b1 +#-----| true -> object creation of type ExceptionA +#-----| false -> {...} + +# 240| throw ...; +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 240| object creation of type ExceptionA +#-----| -> throw ...; +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 243| {...} +#-----| -> try {...} ... + +# 243| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] try {...} ... + +# 243| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] try {...} ... + +# 244| try {...} ... +#-----| -> {...} + +# 244| [finally: exception(Exception)] try {...} ... +#-----| -> [finally: exception(Exception)] {...} + +# 244| [finally: exception(ExceptionA)] try {...} ... +#-----| -> [finally: exception(ExceptionA)] {...} + +# 245| {...} +#-----| -> if (...) ... + +# 245| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] if (...) ... + +# 245| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] if (...) ... + +# 246| if (...) ... +#-----| -> access to parameter b2 + +# 246| [finally: exception(Exception)] if (...) ... +#-----| -> [finally: exception(Exception)] access to parameter b2 + +# 246| [finally: exception(ExceptionA)] if (...) ... +#-----| -> [finally: exception(ExceptionA)] access to parameter b2 + +# 246| access to parameter b2 +#-----| true -> object creation of type ExceptionA +#-----| false -> {...} + +# 246| [finally: exception(Exception)] access to parameter b2 +#-----| true -> [finally: exception(Exception)] object creation of type ExceptionA +#-----| false -> [finally: exception(Exception)] {...} + +# 246| [finally: exception(ExceptionA)] access to parameter b2 +#-----| true -> [finally: exception(ExceptionA)] object creation of type ExceptionA +#-----| false -> [finally: exception(ExceptionA)] {...} + +# 247| throw ...; +#-----| exception(ExceptionA) -> [finally(1): exception(ExceptionA)] {...} + +# 247| [finally: exception(Exception)] throw ...; +#-----| exception(ExceptionA) -> [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} + +# 247| [finally: exception(ExceptionA)] throw ...; +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} + +# 247| object creation of type ExceptionA +#-----| -> throw ...; +#-----| exception(Exception) -> [finally(1): exception(Exception)] {...} + +# 247| [finally: exception(Exception)] object creation of type ExceptionA +#-----| -> [finally: exception(Exception)] throw ...; +#-----| exception(Exception) -> [finally: exception(Exception), finally(1): exception(Exception)] {...} + +# 247| [finally: exception(ExceptionA)] object creation of type ExceptionA +#-----| -> [finally: exception(ExceptionA)] throw ...; +#-----| exception(Exception) -> [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} + +# 250| {...} +#-----| -> ...; + +# 250| [finally(1): exception(Exception)] {...} +#-----| -> [finally(1): exception(Exception)] ...; + +# 250| [finally(1): exception(ExceptionA)] {...} +#-----| -> [finally(1): exception(ExceptionA)] ...; + +# 250| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 250| [finally: exception(Exception), finally(1): exception(Exception)] {...} +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] ...; + +# 250| [finally: exception(Exception), finally(1): exception(ExceptionA)] {...} +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; + +# 250| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] ...; + +# 250| [finally: exception(ExceptionA), finally(1): exception(Exception)] {...} +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; + +# 250| [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; + +# 251| ...; +#-----| -> "Inner finally" + +# 251| [finally(1): exception(Exception)] ...; +#-----| -> [finally(1): exception(Exception)] "Inner finally" + +# 251| [finally(1): exception(ExceptionA)] ...; +#-----| -> [finally(1): exception(ExceptionA)] "Inner finally" + +# 251| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "Inner finally" + +# 251| [finally: exception(Exception), finally(1): exception(Exception)] ...; +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" + +# 251| [finally: exception(Exception), finally(1): exception(ExceptionA)] ...; +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" + +# 251| [finally: exception(ExceptionA)] ...; +#-----| -> [finally: exception(ExceptionA)] "Inner finally" + +# 251| [finally: exception(ExceptionA), finally(1): exception(Exception)] ...; +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" + +# 251| [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] ...; +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" + +# 251| call to method WriteLine +#-----| -> ...; + +# 251| [finally(1): exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 251| [finally(1): exception(ExceptionA)] call to method WriteLine +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 251| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 251| [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 251| [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 251| [finally: exception(ExceptionA)] call to method WriteLine +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 251| [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 251| [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine +#-----| exception(ExceptionA) -> [finally: exception(ExceptionA)] {...} + +# 251| "Inner finally" +#-----| -> call to method WriteLine + +# 251| [finally(1): exception(Exception)] "Inner finally" +#-----| -> [finally(1): exception(Exception)] call to method WriteLine + +# 251| [finally(1): exception(ExceptionA)] "Inner finally" +#-----| -> [finally(1): exception(ExceptionA)] call to method WriteLine + +# 251| [finally: exception(Exception)] "Inner finally" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 251| [finally: exception(Exception), finally(1): exception(Exception)] "Inner finally" +#-----| -> [finally: exception(Exception), finally(1): exception(Exception)] call to method WriteLine + +# 251| [finally: exception(Exception), finally(1): exception(ExceptionA)] "Inner finally" +#-----| -> [finally: exception(Exception), finally(1): exception(ExceptionA)] call to method WriteLine + +# 251| [finally: exception(ExceptionA)] "Inner finally" +#-----| -> [finally: exception(ExceptionA)] call to method WriteLine + +# 251| [finally: exception(ExceptionA), finally(1): exception(Exception)] "Inner finally" +#-----| -> [finally: exception(ExceptionA), finally(1): exception(Exception)] call to method WriteLine + +# 251| [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] "Inner finally" +#-----| -> [finally: exception(ExceptionA), finally(1): exception(ExceptionA)] call to method WriteLine + +# 254| ...; +#-----| -> "Mid finally" + +# 254| call to method WriteLine +#-----| -> {...} +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 254| "Mid finally" +#-----| -> call to method WriteLine + +# 257| {...} +#-----| -> ...; + +# 257| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 257| [finally: exception(ExceptionA)] {...} +#-----| -> [finally: exception(ExceptionA)] ...; + +# 258| ...; +#-----| -> "Outer finally" + +# 258| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "Outer finally" + +# 258| [finally: exception(ExceptionA)] ...; +#-----| -> [finally: exception(ExceptionA)] "Outer finally" + +# 258| call to method WriteLine +#-----| -> ...; + +# 258| [finally: exception(Exception)] call to method WriteLine +#-----| exception(Exception) -> exit M12 (abnormal) + +# 258| [finally: exception(ExceptionA)] call to method WriteLine +#-----| exception(ExceptionA) -> exit M12 (abnormal) + +# 258| "Outer finally" +#-----| -> call to method WriteLine + +# 258| [finally: exception(Exception)] "Outer finally" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 258| [finally: exception(ExceptionA)] "Outer finally" +#-----| -> [finally: exception(ExceptionA)] call to method WriteLine + +# 260| ...; +#-----| -> "Done" + +# 260| call to method WriteLine +#-----| -> exit M12 (normal) + +# 260| "Done" +#-----| -> call to method WriteLine + +# 263| enter M13 +#-----| -> {...} + +# 263| exit M13 + +# 263| exit M13 (abnormal) +#-----| -> exit M13 + +# 263| exit M13 (normal) +#-----| -> exit M13 + +# 264| {...} +#-----| -> try {...} ... + +# 265| try {...} ... +#-----| -> {...} + +# 266| {...} +#-----| -> ...; + +# 267| ...; +#-----| -> "1" + +# 267| call to method WriteLine +#-----| -> {...} +#-----| exception(Exception) -> [finally: exception(Exception)] {...} + +# 267| "1" +#-----| -> call to method WriteLine + +# 270| {...} +#-----| -> ...; + +# 270| [finally: exception(Exception)] {...} +#-----| -> [finally: exception(Exception)] ...; + +# 271| ...; +#-----| -> "3" + +# 271| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] "3" + +# 271| call to method WriteLine +#-----| -> ...; + +# 271| [finally: exception(Exception)] call to method WriteLine +#-----| -> [finally: exception(Exception)] ...; + +# 271| "3" +#-----| -> call to method WriteLine + +# 271| [finally: exception(Exception)] "3" +#-----| -> [finally: exception(Exception)] call to method WriteLine + +# 272| ...; +#-----| -> access to parameter i + +# 272| [finally: exception(Exception)] ...; +#-----| -> [finally: exception(Exception)] access to parameter i + +# 272| ... = ... +#-----| -> exit M13 (normal) + +# 272| [finally: exception(Exception)] ... = ... +#-----| exception(Exception) -> exit M13 (abnormal) + +# 272| ... + ... +#-----| -> ... = ... + +# 272| [finally: exception(Exception)] ... + ... +#-----| -> [finally: exception(Exception)] ... = ... + +# 272| access to parameter i +#-----| -> 3 + +# 272| [finally: exception(Exception)] access to parameter i +#-----| -> [finally: exception(Exception)] 3 + +# 272| 3 +#-----| -> ... + ... + +# 272| [finally: exception(Exception)] 3 +#-----| -> [finally: exception(Exception)] ... + ... + +Foreach.cs: +# 6| enter M1 +#-----| -> {...} + +# 6| exit M1 + +# 6| exit M1 (normal) +#-----| -> exit M1 + +# 7| {...} +#-----| -> access to parameter args + +# 8| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> exit M1 (normal) + +# 8| String arg +#-----| -> ; + +# 8| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 9| ; +#-----| -> foreach (... ... in ...) ... + +# 12| enter M2 +#-----| -> {...} + +# 12| exit M2 + +# 12| exit M2 (normal) +#-----| -> exit M2 + +# 13| {...} +#-----| -> access to parameter args + +# 14| foreach (... ... in ...) ... +#-----| non-empty -> String _ +#-----| empty -> exit M2 (normal) + +# 14| String _ +#-----| -> ; + +# 14| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 15| ; +#-----| -> foreach (... ... in ...) ... + +# 18| enter M3 +#-----| -> {...} + +# 18| exit M3 + +# 18| exit M3 (normal) +#-----| -> exit M3 + +# 19| {...} +#-----| -> access to parameter e + +# 20| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M3 (normal) + +# 20| String x +#-----| -> ; + +# 20| ... ?? ... +#-----| -> foreach (... ... in ...) ... + +# 20| access to parameter e +#-----| non-null -> call to method ToArray +#-----| null -> call to method Empty + +# 20| call to method ToArray +#-----| non-null -> ... ?? ... +#-----| null -> call to method Empty + +# 20| call to method Empty +#-----| -> ... ?? ... + +# 21| ; +#-----| -> foreach (... ... in ...) ... + +# 24| enter M4 +#-----| -> {...} + +# 24| exit M4 + +# 24| exit M4 (normal) +#-----| -> exit M4 + +# 25| {...} +#-----| -> access to parameter args + +# 26| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M4 (normal) + +# 26| (..., ...) +#-----| -> ; + +# 26| String x +#-----| -> Int32 y + +# 26| Int32 y +#-----| -> (..., ...) + +# 26| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 27| ; +#-----| -> foreach (... ... in ...) ... + +# 30| enter M5 +#-----| -> {...} + +# 30| exit M5 + +# 30| exit M5 (normal) +#-----| -> exit M5 + +# 31| {...} +#-----| -> access to parameter args + +# 32| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M5 (normal) + +# 32| (..., ...) +#-----| -> ; + +# 32| String x +#-----| -> Int32 y + +# 32| Int32 y +#-----| -> (..., ...) + +# 32| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 33| ; +#-----| -> foreach (... ... in ...) ... + +# 36| enter M6 +#-----| -> {...} + +# 36| exit M6 + +# 36| exit M6 (normal) +#-----| -> exit M6 + +# 37| {...} +#-----| -> access to parameter args + +# 38| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M6 (normal) + +# 38| (..., ...) +#-----| -> ; + +# 38| String x +#-----| -> Int32 y + +# 38| Int32 y +#-----| -> (..., ...) + +# 38| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 39| ; +#-----| -> foreach (... ... in ...) ... + +Initializers.cs: +# 5| ... = ... +#-----| -> this access + +# 5| ... = ... +#-----| -> this access + +# 5| this access +#-----| -> access to field H + +# 5| this access +#-----| -> access to field H + +# 5| ... + ... +#-----| -> ... = ... + +# 5| ... + ... +#-----| -> ... = ... + +# 5| access to field H +#-----| -> 1 + +# 5| access to field H +#-----| -> 1 + +# 5| 1 +#-----| -> ... + ... + +# 5| 1 +#-----| -> ... + ... + +# 6| access to property G +#-----| -> ... = ... + +# 6| access to property G +#-----| -> ... = ... + +# 6| this access +#-----| -> access to field H + +# 6| this access +#-----| -> access to field H + +# 6| ... = ... +#-----| -> {...} + +# 6| ... = ... +#-----| -> {...} + +# 6| ... + ... +#-----| -> access to property G + +# 6| ... + ... +#-----| -> access to property G + +# 6| access to field H +#-----| -> 2 + +# 6| access to field H +#-----| -> 2 + +# 6| 2 +#-----| -> ... + ... + +# 6| 2 +#-----| -> ... + ... + +# 8| enter Initializers +#-----| -> call to constructor Object + +# 8| call to constructor Object +#-----| -> this access + +# 8| exit Initializers + +# 8| exit Initializers (normal) +#-----| -> exit Initializers + +# 8| {...} +#-----| -> exit Initializers (normal) + +# 10| enter Initializers +#-----| -> call to constructor Object + +# 10| call to constructor Object +#-----| -> this access + +# 10| exit Initializers + +# 10| exit Initializers (normal) +#-----| -> exit Initializers + +# 10| {...} +#-----| -> exit Initializers (normal) + +# 12| enter M +#-----| -> {...} + +# 12| exit M + +# 12| exit M (normal) +#-----| -> exit M + +# 13| {...} +#-----| -> ... ...; + +# 14| ... ...; +#-----| -> "" + +# 14| Initializers i = ... +#-----| -> ... ...; + +# 14| object creation of type Initializers +#-----| -> 0 + +# 14| "" +#-----| -> object creation of type Initializers + +# 14| { ..., ... } +#-----| -> Initializers i = ... + +# 14| ... = ... +#-----| -> 1 + +# 14| 0 +#-----| -> ... = ... + +# 14| ... = ... +#-----| -> { ..., ... } + +# 14| access to property G +#-----| -> ... = ... + +# 14| 1 +#-----| -> access to property G + +# 15| ... ...; +#-----| -> 2 + +# 15| Initializers[] iz = ... +#-----| -> exit M (normal) + +# 15| array creation of type Initializers[] +#-----| -> access to local variable i + +# 15| 2 +#-----| -> array creation of type Initializers[] + +# 15| { ..., ... } +#-----| -> Initializers[] iz = ... + +# 15| access to local variable i +#-----| -> "" + +# 15| object creation of type Initializers +#-----| -> { ..., ... } + +# 15| "" +#-----| -> object creation of type Initializers + +# 18| enter H +#-----| -> 1 + +# 18| ... = ... + +# 18| 1 +#-----| -> ... = ... + +# 20| enter NoConstructor +#-----| -> this access + +# 20| exit NoConstructor + +# 20| exit NoConstructor (normal) +#-----| -> exit NoConstructor + +# 22| ... = ... +#-----| -> this access + +# 22| this access +#-----| -> 0 + +# 22| 0 +#-----| -> ... = ... + +# 23| ... = ... +#-----| -> exit NoConstructor (normal) + +# 23| this access +#-----| -> 1 + +# 23| 1 +#-----| -> ... = ... + +# 28| ... = ... +#-----| -> {...} + +# 28| ... = ... +#-----| -> {...} + +# 28| this access +#-----| -> 2 + +# 28| this access +#-----| -> 2 + +# 28| 2 +#-----| -> ... = ... + +# 28| 2 +#-----| -> ... = ... + +# 31| enter Sub +#-----| -> call to constructor NoConstructor + +# 31| exit Sub + +# 31| exit Sub (normal) +#-----| -> exit Sub + +# 31| call to constructor NoConstructor +#-----| -> this access + +# 31| {...} +#-----| -> ...; + +# 31| ...; +#-----| -> this access + +# 31| ... = ... +#-----| -> exit Sub (normal) + +# 31| this access +#-----| -> 3 + +# 31| 3 +#-----| -> ... = ... + +# 33| enter Sub +#-----| -> call to constructor Sub + +# 33| exit Sub + +# 33| exit Sub (normal) +#-----| -> exit Sub + +# 33| call to constructor Sub +#-----| -> {...} + +# 33| {...} +#-----| -> ...; + +# 33| ...; +#-----| -> this access + +# 33| ... = ... +#-----| -> exit Sub (normal) + +# 33| this access +#-----| -> access to parameter i + +# 33| access to parameter i +#-----| -> ... = ... + +# 35| enter Sub +#-----| -> call to constructor NoConstructor + +# 35| call to constructor NoConstructor +#-----| -> this access + +# 35| exit Sub + +# 35| exit Sub (normal) +#-----| -> exit Sub + +# 35| {...} +#-----| -> ...; + +# 35| ...; +#-----| -> this access + +# 35| ... = ... +#-----| -> exit Sub (normal) + +# 35| this access +#-----| -> access to parameter i + +# 35| ... + ... +#-----| -> ... = ... + +# 35| access to parameter i +#-----| -> access to parameter j + +# 35| access to parameter j +#-----| -> ... + ... + +# 51| enter Test +#-----| -> {...} + +# 51| exit Test + +# 51| exit Test (normal) +#-----| -> exit Test + +# 52| {...} +#-----| -> ... ...; + +# 54| ... ...; +#-----| -> object creation of type Dictionary + +# 54| Dictionary dict = ... +#-----| -> ... ...; + +# 54| object creation of type Dictionary +#-----| -> 0 + +# 54| { ..., ... } +#-----| -> Dictionary dict = ... + +# 54| ... = ... +#-----| -> 1 + +# 54| access to indexer +#-----| -> ... = ... + +# 54| 0 +#-----| -> "Zero" + +# 54| "Zero" +#-----| -> access to indexer + +# 54| ... = ... +#-----| -> access to parameter i + +# 54| access to indexer +#-----| -> ... = ... + +# 54| 1 +#-----| -> "One" + +# 54| "One" +#-----| -> access to indexer + +# 54| ... = ... +#-----| -> { ..., ... } + +# 54| access to indexer +#-----| -> ... = ... + +# 54| ... + ... +#-----| -> "Two" + +# 54| access to parameter i +#-----| -> 2 + +# 54| 2 +#-----| -> ... + ... + +# 54| "Two" +#-----| -> access to indexer + +# 57| ... ...; +#-----| -> object creation of type Compound + +# 57| Compound compound = ... +#-----| -> exit Test (normal) + +# 57| object creation of type Compound +#-----| -> 0 + +# 58| { ..., ... } +#-----| -> Compound compound = ... + +# 59| ... = ... +#-----| -> 3 + +# 59| { ..., ... } +#-----| -> ... = ... + +# 59| ... = ... +#-----| -> 1 + +# 59| access to indexer +#-----| -> ... = ... + +# 59| 0 +#-----| -> "Zero" + +# 59| "Zero" +#-----| -> access to indexer + +# 59| ... = ... +#-----| -> access to parameter i + +# 59| access to indexer +#-----| -> ... = ... + +# 59| 1 +#-----| -> "One" + +# 59| "One" +#-----| -> access to indexer + +# 59| ... = ... +#-----| -> { ..., ... } + +# 59| access to indexer +#-----| -> ... = ... + +# 59| ... + ... +#-----| -> "Two" + +# 59| access to parameter i +#-----| -> 2 + +# 59| 2 +#-----| -> ... + ... + +# 59| "Two" +#-----| -> access to indexer + +# 60| ... = ... +#-----| -> 0 + +# 60| access to property DictionaryProperty +#-----| -> ... = ... + +# 60| { ..., ... } +#-----| -> access to property DictionaryProperty + +# 60| ... = ... +#-----| -> 2 + +# 60| access to indexer +#-----| -> ... = ... + +# 60| 3 +#-----| -> "Three" + +# 60| "Three" +#-----| -> access to indexer + +# 60| ... = ... +#-----| -> access to parameter i + +# 60| access to indexer +#-----| -> ... = ... + +# 60| 2 +#-----| -> "Two" + +# 60| "Two" +#-----| -> access to indexer + +# 60| ... = ... +#-----| -> { ..., ... } + +# 60| access to indexer +#-----| -> ... = ... + +# 60| ... + ... +#-----| -> "One" + +# 60| access to parameter i +#-----| -> 1 + +# 60| 1 +#-----| -> ... + ... + +# 60| "One" +#-----| -> access to indexer + +# 61| ... = ... +#-----| -> 0 + +# 61| { ..., ... } +#-----| -> ... = ... + +# 61| ... = ... +#-----| -> access to parameter i + +# 61| 0 +#-----| -> "Zero" + +# 61| "Zero" +#-----| -> ... = ... + +# 61| ... = ... +#-----| -> { ..., ... } + +# 61| ... + ... +#-----| -> "One" + +# 61| access to parameter i +#-----| -> 1 + +# 61| 1 +#-----| -> ... + ... + +# 61| "One" +#-----| -> ... = ... + +# 62| ... = ... +#-----| -> 1 + +# 62| { ..., ... } +#-----| -> ... = ... + +# 62| ... = ... +#-----| -> 1 + +# 62| 0 +#-----| -> 1 + +# 62| 1 +#-----| -> "i" + +# 62| "i" +#-----| -> ... = ... + +# 62| ... = ... +#-----| -> { ..., ... } + +# 62| 1 +#-----| -> access to parameter i + +# 62| ... + ... +#-----| -> "1" + +# 62| access to parameter i +#-----| -> 0 + +# 62| 0 +#-----| -> ... + ... + +# 62| "1" +#-----| -> ... = ... + +# 63| ... = ... +#-----| -> 0 + +# 63| access to property ArrayProperty +#-----| -> ... = ... + +# 63| { ..., ... } +#-----| -> access to property ArrayProperty + +# 63| ... = ... +#-----| -> access to parameter i + +# 63| 1 +#-----| -> "One" + +# 63| "One" +#-----| -> ... = ... + +# 63| ... = ... +#-----| -> { ..., ... } + +# 63| ... + ... +#-----| -> "Two" + +# 63| access to parameter i +#-----| -> 2 + +# 63| 2 +#-----| -> ... + ... + +# 63| "Two" +#-----| -> ... = ... + +# 64| ... = ... +#-----| -> { ..., ... } + +# 64| access to property ArrayProperty2 +#-----| -> ... = ... + +# 64| { ..., ... } +#-----| -> access to property ArrayProperty2 + +# 64| ... = ... +#-----| -> 1 + +# 64| 0 +#-----| -> 1 + +# 64| 1 +#-----| -> "i" + +# 64| "i" +#-----| -> ... = ... + +# 64| ... = ... +#-----| -> { ..., ... } + +# 64| 1 +#-----| -> access to parameter i + +# 64| ... + ... +#-----| -> "1" + +# 64| access to parameter i +#-----| -> 0 + +# 64| 0 +#-----| -> ... + ... + +# 64| "1" +#-----| -> ... = ... + +LoopUnrolling.cs: +# 7| enter M1 +#-----| -> {...} + +# 7| exit M1 + +# 7| exit M1 (normal) +#-----| -> exit M1 + +# 8| {...} +#-----| -> if (...) ... + +# 9| if (...) ... +#-----| -> access to parameter args + +# 9| ... == ... +#-----| true -> return ...; +#-----| false -> access to parameter args + +# 9| access to property Length +#-----| -> 0 + +# 9| access to parameter args +#-----| -> access to property Length + +# 9| 0 +#-----| -> ... == ... + +# 10| return ...; +#-----| return -> exit M1 (normal) + +# 11| foreach (... ... in ...) ... +#-----| non-empty -> String arg +#-----| empty -> exit M1 (normal) + +# 11| [unroll (line 11)] foreach (... ... in ...) ... +#-----| non-empty -> String arg + +# 11| String arg +#-----| -> ...; + +# 11| access to parameter args +#-----| -> [unroll (line 11)] foreach (... ... in ...) ... + +# 12| ...; +#-----| -> access to local variable arg + +# 12| call to method WriteLine +#-----| -> foreach (... ... in ...) ... + +# 12| access to local variable arg +#-----| -> call to method WriteLine + +# 15| enter M2 +#-----| -> {...} + +# 15| exit M2 + +# 15| exit M2 (normal) +#-----| -> exit M2 + +# 16| {...} +#-----| -> ... ...; + +# 17| ... ...; +#-----| -> 3 + +# 17| String[] xs = ... +#-----| -> access to local variable xs + +# 17| array creation of type String[] +#-----| -> "a" + +# 17| 3 +#-----| -> array creation of type String[] + +# 17| { ..., ... } +#-----| -> String[] xs = ... + +# 17| "a" +#-----| -> "b" + +# 17| "b" +#-----| -> "c" + +# 17| "c" +#-----| -> { ..., ... } + +# 18| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M2 (normal) + +# 18| [unroll (line 18)] foreach (... ... in ...) ... +#-----| non-empty -> String x + +# 18| String x +#-----| -> ...; + +# 18| access to local variable xs +#-----| -> [unroll (line 18)] foreach (... ... in ...) ... + +# 19| ...; +#-----| -> access to local variable x + +# 19| call to method WriteLine +#-----| -> foreach (... ... in ...) ... + +# 19| access to local variable x +#-----| -> call to method WriteLine + +# 22| enter M3 +#-----| -> {...} + +# 22| exit M3 + +# 22| exit M3 (normal) +#-----| -> exit M3 + +# 23| {...} +#-----| -> access to parameter args + +# 24| foreach (... ... in ...) ... +#-----| non-empty -> Char arg +#-----| empty -> exit M3 (normal) + +# 24| Char arg +#-----| -> access to parameter args + +# 24| access to parameter args +#-----| -> foreach (... ... in ...) ... + +# 25| foreach (... ... in ...) ... +#-----| empty -> foreach (... ... in ...) ... +#-----| non-empty -> Char arg0 + +# 25| [unroll (line 25)] foreach (... ... in ...) ... +#-----| non-empty -> Char arg0 + +# 25| Char arg0 +#-----| -> ...; + +# 25| access to parameter args +#-----| -> [unroll (line 25)] foreach (... ... in ...) ... + +# 26| ...; +#-----| -> access to local variable arg0 + +# 26| call to method WriteLine +#-----| -> foreach (... ... in ...) ... + +# 26| access to local variable arg0 +#-----| -> call to method WriteLine + +# 29| enter M4 +#-----| -> {...} + +# 29| exit M4 + +# 29| exit M4 (normal) +#-----| -> exit M4 + +# 30| {...} +#-----| -> ... ...; + +# 31| ... ...; +#-----| -> 0 + +# 31| String[] xs = ... +#-----| -> access to local variable xs + +# 31| array creation of type String[] +#-----| -> String[] xs = ... + +# 31| 0 +#-----| -> array creation of type String[] + +# 32| [skip (line 32)] foreach (... ... in ...) ... +#-----| empty -> exit M4 (normal) + +# 32| access to local variable xs +#-----| -> [skip (line 32)] foreach (... ... in ...) ... + +# 36| enter M5 +#-----| -> {...} + +# 36| exit M5 + +# 36| exit M5 (normal) +#-----| -> exit M5 + +# 37| {...} +#-----| -> ... ...; + +# 38| ... ...; +#-----| -> 3 + +# 38| String[] xs = ... +#-----| -> ... ...; + +# 38| array creation of type String[] +#-----| -> "a" + +# 38| 3 +#-----| -> array creation of type String[] + +# 38| { ..., ... } +#-----| -> String[] xs = ... + +# 38| "a" +#-----| -> "b" + +# 38| "b" +#-----| -> "c" + +# 38| "c" +#-----| -> { ..., ... } + +# 39| ... ...; +#-----| -> 3 + +# 39| String[] ys = ... +#-----| -> access to local variable xs + +# 39| array creation of type String[] +#-----| -> "0" + +# 39| 3 +#-----| -> array creation of type String[] + +# 39| { ..., ... } +#-----| -> String[] ys = ... + +# 39| "0" +#-----| -> "1" + +# 39| "1" +#-----| -> "2" + +# 39| "2" +#-----| -> { ..., ... } + +# 40| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M5 (normal) + +# 40| [unroll (line 40)] foreach (... ... in ...) ... +#-----| non-empty -> String x + +# 40| String x +#-----| -> access to local variable ys + +# 40| access to local variable xs +#-----| -> [unroll (line 40)] foreach (... ... in ...) ... + +# 41| foreach (... ... in ...) ... +#-----| empty -> foreach (... ... in ...) ... +#-----| non-empty -> String y + +# 41| [unroll (line 41)] foreach (... ... in ...) ... +#-----| non-empty -> String y + +# 41| String y +#-----| -> ...; + +# 41| access to local variable ys +#-----| -> [unroll (line 41)] foreach (... ... in ...) ... + +# 42| ...; +#-----| -> access to local variable x + +# 42| call to method WriteLine +#-----| -> foreach (... ... in ...) ... + +# 42| ... + ... +#-----| -> call to method WriteLine + +# 42| access to local variable x +#-----| -> access to local variable y + +# 42| access to local variable y +#-----| -> ... + ... + +# 45| enter M6 +#-----| -> {...} + +# 46| {...} +#-----| -> ... ...; + +# 47| ... ...; +#-----| -> 3 + +# 47| String[] xs = ... +#-----| -> access to local variable xs + +# 47| array creation of type String[] +#-----| -> "a" + +# 47| 3 +#-----| -> array creation of type String[] + +# 47| { ..., ... } +#-----| -> String[] xs = ... + +# 47| "a" +#-----| -> "b" + +# 47| "b" +#-----| -> "c" + +# 47| "c" +#-----| -> { ..., ... } + +# 48| [unroll (line 48)] foreach (... ... in ...) ... +#-----| non-empty -> String x + +# 48| String x +#-----| -> {...} + +# 48| access to local variable xs +#-----| -> [unroll (line 48)] foreach (... ... in ...) ... + +# 49| {...} +#-----| -> Label: + +# 50| Label: +#-----| -> ...; + +# 50| ...; +#-----| -> access to local variable x + +# 50| call to method WriteLine +#-----| -> goto ...; + +# 50| access to local variable x +#-----| -> call to method WriteLine + +# 51| goto ...; +#-----| goto(Label) -> Label: + +# 55| enter M7 +#-----| -> {...} + +# 55| exit M7 + +# 55| exit M7 (normal) +#-----| -> exit M7 + +# 56| {...} +#-----| -> ... ...; + +# 57| ... ...; +#-----| -> 3 + +# 57| String[] xs = ... +#-----| -> access to local variable xs + +# 57| array creation of type String[] +#-----| -> "a" + +# 57| 3 +#-----| -> array creation of type String[] + +# 57| { ..., ... } +#-----| -> String[] xs = ... + +# 57| "a" +#-----| -> "b" + +# 57| "b" +#-----| -> "c" + +# 57| "c" +#-----| -> { ..., ... } + +# 58| [unroll (line 58)] foreach (... ... in ...) ... +#-----| non-empty -> String x + +# 58| [b (line 55): false] foreach (... ... in ...) ... +#-----| non-empty -> [b (line 55): false] String x +#-----| empty -> exit M7 (normal) + +# 58| [b (line 55): true] foreach (... ... in ...) ... +#-----| non-empty -> [b (line 55): true] String x +#-----| empty -> exit M7 (normal) + +# 58| String x +#-----| -> {...} + +# 58| [b (line 55): false] String x +#-----| -> [b (line 55): false] {...} + +# 58| [b (line 55): true] String x +#-----| -> [b (line 55): true] {...} + +# 58| access to local variable xs +#-----| -> [unroll (line 58)] foreach (... ... in ...) ... + +# 59| {...} +#-----| -> if (...) ... + +# 59| [b (line 55): false] {...} +#-----| -> [b (line 55): false] if (...) ... + +# 59| [b (line 55): true] {...} +#-----| -> [b (line 55): true] if (...) ... + +# 60| if (...) ... +#-----| -> access to parameter b + +# 60| [b (line 55): false] if (...) ... +#-----| -> [b (line 55): false] access to parameter b + +# 60| [b (line 55): true] if (...) ... +#-----| -> [b (line 55): true] access to parameter b + +# 60| access to parameter b +#-----| true -> [b (line 55): true] ...; +#-----| false -> [b (line 55): false] if (...) ... + +# 60| [b (line 55): false] access to parameter b +#-----| false -> [b (line 55): false] if (...) ... + +# 60| [b (line 55): true] access to parameter b +#-----| true -> [b (line 55): true] ...; + +# 61| [b (line 55): true] ...; +#-----| -> [b (line 55): true] access to local variable x + +# 61| [b (line 55): true] call to method WriteLine +#-----| -> [b (line 55): true] if (...) ... + +# 61| [b (line 55): true] access to local variable x +#-----| -> [b (line 55): true] call to method WriteLine + +# 62| [b (line 55): false] if (...) ... +#-----| -> [b (line 55): false] access to parameter b + +# 62| [b (line 55): true] if (...) ... +#-----| -> [b (line 55): true] access to parameter b + +# 62| [b (line 55): false] access to parameter b +#-----| false -> [b (line 55): false] foreach (... ... in ...) ... + +# 62| [b (line 55): true] access to parameter b +#-----| true -> [b (line 55): true] ...; + +# 63| [b (line 55): true] ...; +#-----| -> [b (line 55): true] access to local variable x + +# 63| [b (line 55): true] call to method WriteLine +#-----| -> [b (line 55): true] foreach (... ... in ...) ... + +# 63| [b (line 55): true] access to local variable x +#-----| -> [b (line 55): true] call to method WriteLine + +# 67| enter M8 +#-----| -> {...} + +# 67| exit M8 + +# 67| exit M8 (normal) +#-----| -> exit M8 + +# 68| {...} +#-----| -> if (...) ... + +# 69| if (...) ... +#-----| -> access to parameter args + +# 69| [false] !... +#-----| false -> ...; + +# 69| [true] !... +#-----| true -> return ...; + +# 69| call to method Any +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 69| access to parameter args +#-----| -> call to method Any + +# 70| return ...; +#-----| return -> exit M8 (normal) + +# 71| ...; +#-----| -> access to parameter args + +# 71| call to method Clear +#-----| -> access to parameter args + +# 71| access to parameter args +#-----| -> call to method Clear + +# 72| [skip (line 72)] foreach (... ... in ...) ... +#-----| empty -> exit M8 (normal) + +# 72| access to parameter args +#-----| -> [skip (line 72)] foreach (... ... in ...) ... + +# 76| enter M9 +#-----| -> {...} + +# 76| exit M9 + +# 76| exit M9 (normal) +#-----| -> exit M9 + +# 77| {...} +#-----| -> ... ...; + +# 78| ... ...; +#-----| -> 2 + +# 78| String[,] xs = ... +#-----| -> access to local variable xs + +# 78| array creation of type String[,] +#-----| -> String[,] xs = ... + +# 78| 2 +#-----| -> 0 + +# 78| 0 +#-----| -> array creation of type String[,] + +# 79| [skip (line 79)] foreach (... ... in ...) ... +#-----| empty -> exit M9 (normal) + +# 79| access to local variable xs +#-----| -> [skip (line 79)] foreach (... ... in ...) ... + +# 85| enter M10 +#-----| -> {...} + +# 85| exit M10 + +# 85| exit M10 (normal) +#-----| -> exit M10 + +# 86| {...} +#-----| -> ... ...; + +# 87| ... ...; +#-----| -> 0 + +# 87| String[,] xs = ... +#-----| -> access to local variable xs + +# 87| array creation of type String[,] +#-----| -> String[,] xs = ... + +# 87| 0 +#-----| -> 2 + +# 87| 2 +#-----| -> array creation of type String[,] + +# 88| [skip (line 88)] foreach (... ... in ...) ... +#-----| empty -> exit M10 (normal) + +# 88| access to local variable xs +#-----| -> [skip (line 88)] foreach (... ... in ...) ... + +# 94| enter M11 +#-----| -> {...} + +# 94| exit M11 + +# 94| exit M11 (normal) +#-----| -> exit M11 + +# 95| {...} +#-----| -> ... ...; + +# 96| ... ...; +#-----| -> 2 + +# 96| String[,] xs = ... +#-----| -> access to local variable xs + +# 96| array creation of type String[,] +#-----| -> String[,] xs = ... + +# 96| 2 +#-----| -> 2 + +# 96| 2 +#-----| -> array creation of type String[,] + +# 97| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit M11 (normal) + +# 97| [unroll (line 97)] foreach (... ... in ...) ... +#-----| non-empty -> String x + +# 97| String x +#-----| -> {...} + +# 97| access to local variable xs +#-----| -> [unroll (line 97)] foreach (... ... in ...) ... + +# 98| {...} +#-----| -> ...; + +# 99| ...; +#-----| -> access to local variable x + +# 99| call to method WriteLine +#-----| -> foreach (... ... in ...) ... + +# 99| access to local variable x +#-----| -> call to method WriteLine + +MultiImplementationA.cs: +# 6| throw ... +#-----| exception(NullReferenceException) -> exit get_P1 (abnormal) +#-----| exception(NullReferenceException) -> exit get_P1 (abnormal) + +# 6| null +#-----| -> throw ... + +# 7| {...} +#-----| -> null + +# 7| throw ...; +#-----| exception(NullReferenceException) -> exit get_P2 (abnormal) +#-----| exception(NullReferenceException) -> exit get_P2 (abnormal) + +# 7| null +#-----| -> throw ...; + +# 7| {...} +#-----| -> null + +# 7| throw ...; +#-----| exception(NullReferenceException) -> exit set_P2 (abnormal) +#-----| exception(NullReferenceException) -> exit set_P2 (abnormal) + +# 7| null +#-----| -> throw ...; + +# 8| throw ... +#-----| exception(NullReferenceException) -> exit M (abnormal) +#-----| exception(NullReferenceException) -> exit M (abnormal) + +# 8| null +#-----| -> throw ... + +# 13| ... = ... +#-----| -> this access + +# 13| this access +#-----| -> 0 + +# 13| 0 +#-----| -> ... = ... + +# 14| access to parameter i +#-----| -> exit get_Item (normal) +#-----| -> exit get_Item (normal) + +# 15| {...} +#-----| -> access to parameter s + +# 15| return ...; +#-----| return -> exit get_Item (normal) +#-----| return -> exit get_Item (normal) + +# 15| access to parameter s +#-----| -> return ...; + +# 15| {...} +#-----| -> exit set_Item (normal) +#-----| -> exit set_Item (normal) + +# 17| {...} +#-----| -> M2(...) + +# 18| enter M2 +#-----| -> 0 + +# 18| M2(...) +#-----| -> exit M1 (normal) +#-----| -> exit M1 (normal) + +# 18| exit M2 + +# 18| exit M2 (normal) +#-----| -> exit M2 + +# 18| 0 +#-----| -> exit M2 (normal) + +# 20| call to constructor Object +#-----| -> this access + +# 20| {...} +#-----| -> ...; + +# 20| ...; +#-----| -> this access + +# 20| ... = ... +#-----| -> exit C2 (normal) +#-----| -> exit C2 (normal) + +# 20| this access +#-----| -> access to parameter i + +# 20| access to parameter i +#-----| -> ... = ... + +# 21| call to constructor C2 +#-----| -> {...} + +# 21| 0 +#-----| -> call to constructor C2 + +# 21| {...} +#-----| -> exit C2 (normal) +#-----| -> exit C2 (normal) + +# 22| {...} +#-----| -> exit ~C2 (normal) +#-----| -> exit ~C2 (normal) + +# 23| null +#-----| -> exit implicit conversion (normal) +#-----| -> exit implicit conversion (normal) + +# 24| access to property P +#-----| -> ... = ... + +# 24| this access +#-----| -> 0 + +# 24| ... = ... +#-----| -> {...} + +# 24| 0 +#-----| -> access to property P + +# 30| throw ... +#-----| exception(NullReferenceException) -> exit get_P3 (abnormal) +#-----| exception(NullReferenceException) -> exit get_P3 (abnormal) + +# 30| null +#-----| -> throw ... + +# 36| {...} +#-----| -> null + +# 36| throw ...; +#-----| exception(NullReferenceException) -> exit M1 (abnormal) +#-----| exception(NullReferenceException) -> exit M1 (abnormal) + +# 36| null +#-----| -> throw ...; + +# 37| enter M2 +#-----| -> {...} + +# 37| exit M2 + +# 37| exit M2 (abnormal) +#-----| -> exit M2 + +# 37| {...} +#-----| -> null + +# 37| throw ...; +#-----| exception(NullReferenceException) -> exit M2 (abnormal) + +# 37| null +#-----| -> throw ...; + +# 6| enter get_P1 +#-----| -> null +#-----| -> 0 + +MultiImplementationB.cs: +# 3| enter get_P1 +#-----| -> null +#-----| -> 0 + +# 3| 0 +#-----| -> exit get_P1 (normal) +#-----| -> exit get_P1 (normal) + +MultiImplementationA.cs: +# 6| exit get_P1 + +MultiImplementationB.cs: +# 3| exit get_P1 + +MultiImplementationA.cs: +# 6| exit get_P1 (abnormal) +#-----| -> exit get_P1 +#-----| -> exit get_P1 + +MultiImplementationB.cs: +# 3| exit get_P1 (abnormal) +#-----| -> exit get_P1 +#-----| -> exit get_P1 + +MultiImplementationA.cs: +# 6| exit get_P1 (normal) +#-----| -> exit get_P1 +#-----| -> exit get_P1 + +MultiImplementationB.cs: +# 3| exit get_P1 (normal) +#-----| -> exit get_P1 +#-----| -> exit get_P1 + +MultiImplementationA.cs: +# 7| enter get_P2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 4| enter get_P2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 7| exit get_P2 + +MultiImplementationB.cs: +# 4| exit get_P2 + +MultiImplementationA.cs: +# 7| exit get_P2 (abnormal) +#-----| -> exit get_P2 +#-----| -> exit get_P2 + +MultiImplementationB.cs: +# 4| exit get_P2 (abnormal) +#-----| -> exit get_P2 +#-----| -> exit get_P2 + +MultiImplementationA.cs: +# 7| exit get_P2 (normal) +#-----| -> exit get_P2 +#-----| -> exit get_P2 + +MultiImplementationB.cs: +# 4| exit get_P2 (normal) +#-----| -> exit get_P2 +#-----| -> exit get_P2 + +# 4| {...} +#-----| -> 1 + +# 4| return ...; +#-----| return -> exit get_P2 (normal) +#-----| return -> exit get_P2 (normal) + +# 4| 1 +#-----| -> return ...; + +MultiImplementationA.cs: +# 7| enter set_P2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 4| enter set_P2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 7| exit set_P2 + +MultiImplementationB.cs: +# 4| exit set_P2 + +MultiImplementationA.cs: +# 7| exit set_P2 (abnormal) +#-----| -> exit set_P2 +#-----| -> exit set_P2 + +MultiImplementationB.cs: +# 4| exit set_P2 (abnormal) +#-----| -> exit set_P2 +#-----| -> exit set_P2 + +MultiImplementationA.cs: +# 7| exit set_P2 (normal) +#-----| -> exit set_P2 +#-----| -> exit set_P2 + +MultiImplementationB.cs: +# 4| exit set_P2 (normal) +#-----| -> exit set_P2 +#-----| -> exit set_P2 + +# 4| {...} +#-----| -> exit set_P2 (normal) +#-----| -> exit set_P2 (normal) + +MultiImplementationA.cs: +# 8| enter M +#-----| -> null +#-----| -> 2 + +MultiImplementationB.cs: +# 5| enter M +#-----| -> null +#-----| -> 2 + +MultiImplementationA.cs: +# 8| exit M + +MultiImplementationB.cs: +# 5| exit M + +MultiImplementationA.cs: +# 8| exit M (abnormal) +#-----| -> exit M +#-----| -> exit M + +MultiImplementationB.cs: +# 5| exit M (abnormal) +#-----| -> exit M +#-----| -> exit M + +MultiImplementationA.cs: +# 8| exit M (normal) +#-----| -> exit M +#-----| -> exit M + +MultiImplementationB.cs: +# 5| exit M (normal) +#-----| -> exit M +#-----| -> exit M + +# 5| 2 +#-----| -> exit M (normal) +#-----| -> exit M (normal) + +# 11| ... = ... +#-----| -> this access + +# 11| this access +#-----| -> 1 + +# 11| 1 +#-----| -> ... = ... + +MultiImplementationA.cs: +# 14| enter get_Item +#-----| -> access to parameter i +#-----| -> null + +MultiImplementationB.cs: +# 12| enter get_Item +#-----| -> access to parameter i +#-----| -> null + +# 12| throw ... +#-----| exception(NullReferenceException) -> exit get_Item (abnormal) +#-----| exception(NullReferenceException) -> exit get_Item (abnormal) + +MultiImplementationA.cs: +# 14| exit get_Item + +MultiImplementationB.cs: +# 12| exit get_Item + +MultiImplementationA.cs: +# 14| exit get_Item (abnormal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationB.cs: +# 12| exit get_Item (abnormal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationA.cs: +# 14| exit get_Item (normal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationB.cs: +# 12| exit get_Item (normal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +# 12| null +#-----| -> throw ... + +MultiImplementationA.cs: +# 15| enter get_Item +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 13| enter get_Item +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 15| exit get_Item + +MultiImplementationB.cs: +# 13| exit get_Item + +MultiImplementationA.cs: +# 15| exit get_Item (abnormal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationB.cs: +# 13| exit get_Item (abnormal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationA.cs: +# 15| exit get_Item (normal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +MultiImplementationB.cs: +# 13| exit get_Item (normal) +#-----| -> exit get_Item +#-----| -> exit get_Item + +# 13| {...} +#-----| -> null + +# 13| throw ...; +#-----| exception(NullReferenceException) -> exit get_Item (abnormal) +#-----| exception(NullReferenceException) -> exit get_Item (abnormal) + +# 13| null +#-----| -> throw ...; + +MultiImplementationA.cs: +# 15| enter set_Item +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 13| enter set_Item +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 15| exit set_Item + +MultiImplementationB.cs: +# 13| exit set_Item + +MultiImplementationA.cs: +# 15| exit set_Item (normal) +#-----| -> exit set_Item +#-----| -> exit set_Item + +MultiImplementationB.cs: +# 13| exit set_Item (normal) +#-----| -> exit set_Item +#-----| -> exit set_Item + +# 13| {...} +#-----| -> exit set_Item (normal) +#-----| -> exit set_Item (normal) + +MultiImplementationA.cs: +# 16| enter M1 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 14| enter M1 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 16| exit M1 + +MultiImplementationB.cs: +# 14| exit M1 + +MultiImplementationA.cs: +# 16| exit M1 (normal) +#-----| -> exit M1 +#-----| -> exit M1 + +MultiImplementationB.cs: +# 14| exit M1 (normal) +#-----| -> exit M1 +#-----| -> exit M1 + +# 15| {...} +#-----| -> M2(...) + +# 16| enter M2 +#-----| -> null + +# 16| M2(...) +#-----| -> exit M1 (normal) +#-----| -> exit M1 (normal) + +# 16| exit M2 + +# 16| exit M2 (abnormal) +#-----| -> exit M2 + +# 16| throw ... +#-----| exception(NullReferenceException) -> exit M2 (abnormal) + +# 16| null +#-----| -> throw ... + +MultiImplementationA.cs: +# 20| enter C2 +#-----| -> call to constructor Object +#-----| -> call to constructor Object + +MultiImplementationB.cs: +# 18| enter C2 +#-----| -> call to constructor Object +#-----| -> call to constructor Object + +# 18| call to constructor Object +#-----| -> this access + +MultiImplementationA.cs: +# 20| exit C2 + +MultiImplementationB.cs: +# 18| exit C2 + +MultiImplementationA.cs: +# 20| exit C2 (abnormal) +#-----| -> exit C2 +#-----| -> exit C2 + +MultiImplementationB.cs: +# 18| exit C2 (abnormal) +#-----| -> exit C2 +#-----| -> exit C2 + +MultiImplementationA.cs: +# 20| exit C2 (normal) +#-----| -> exit C2 +#-----| -> exit C2 + +MultiImplementationB.cs: +# 18| exit C2 (normal) +#-----| -> exit C2 +#-----| -> exit C2 + +# 18| {...} +#-----| -> null + +# 18| throw ...; +#-----| exception(NullReferenceException) -> exit C2 (abnormal) +#-----| exception(NullReferenceException) -> exit C2 (abnormal) + +# 18| null +#-----| -> throw ...; + +MultiImplementationA.cs: +# 21| enter C2 +#-----| -> 0 +#-----| -> 1 + +MultiImplementationB.cs: +# 19| enter C2 +#-----| -> 0 +#-----| -> 1 + +MultiImplementationA.cs: +# 21| exit C2 + +MultiImplementationB.cs: +# 19| exit C2 + +MultiImplementationA.cs: +# 21| exit C2 (normal) +#-----| -> exit C2 +#-----| -> exit C2 + +MultiImplementationB.cs: +# 19| exit C2 (normal) +#-----| -> exit C2 +#-----| -> exit C2 + +# 19| call to constructor C2 +#-----| -> {...} + +# 19| 1 +#-----| -> call to constructor C2 + +# 19| {...} +#-----| -> exit C2 (normal) +#-----| -> exit C2 (normal) + +MultiImplementationA.cs: +# 22| enter ~C2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationB.cs: +# 20| enter ~C2 +#-----| -> {...} +#-----| -> {...} + +MultiImplementationA.cs: +# 22| exit ~C2 + +MultiImplementationB.cs: +# 20| exit ~C2 + +MultiImplementationA.cs: +# 22| exit ~C2 (abnormal) +#-----| -> exit ~C2 +#-----| -> exit ~C2 + +MultiImplementationB.cs: +# 20| exit ~C2 (abnormal) +#-----| -> exit ~C2 +#-----| -> exit ~C2 + +MultiImplementationA.cs: +# 22| exit ~C2 (normal) +#-----| -> exit ~C2 +#-----| -> exit ~C2 + +MultiImplementationB.cs: +# 20| exit ~C2 (normal) +#-----| -> exit ~C2 +#-----| -> exit ~C2 + +# 20| {...} +#-----| -> null + +# 20| throw ...; +#-----| exception(NullReferenceException) -> exit ~C2 (abnormal) +#-----| exception(NullReferenceException) -> exit ~C2 (abnormal) + +# 20| null +#-----| -> throw ...; + +MultiImplementationA.cs: +# 23| enter implicit conversion +#-----| -> null +#-----| -> null + +MultiImplementationB.cs: +# 21| enter implicit conversion +#-----| -> null +#-----| -> null + +MultiImplementationA.cs: +# 23| exit implicit conversion + +MultiImplementationB.cs: +# 21| exit implicit conversion + +MultiImplementationA.cs: +# 23| exit implicit conversion (abnormal) +#-----| -> exit implicit conversion +#-----| -> exit implicit conversion + +MultiImplementationB.cs: +# 21| exit implicit conversion (abnormal) +#-----| -> exit implicit conversion +#-----| -> exit implicit conversion + +MultiImplementationA.cs: +# 23| exit implicit conversion (normal) +#-----| -> exit implicit conversion +#-----| -> exit implicit conversion + +MultiImplementationB.cs: +# 21| exit implicit conversion (normal) +#-----| -> exit implicit conversion +#-----| -> exit implicit conversion + +# 21| throw ... +#-----| exception(NullReferenceException) -> exit implicit conversion (abnormal) +#-----| exception(NullReferenceException) -> exit implicit conversion (abnormal) + +# 21| null +#-----| -> throw ... + +# 22| access to property P +#-----| -> ... = ... + +# 22| this access +#-----| -> 1 + +# 22| ... = ... +#-----| -> {...} + +# 22| 1 +#-----| -> access to property P + +MultiImplementationA.cs: +# 30| enter get_P3 +#-----| -> null + +MultiImplementationB.cs: +# 27| enter get_P3 +#-----| -> null + +MultiImplementationA.cs: +# 30| exit get_P3 + +MultiImplementationB.cs: +# 27| exit get_P3 + +MultiImplementationA.cs: +# 30| exit get_P3 (abnormal) +#-----| -> exit get_P3 +#-----| -> exit get_P3 + +MultiImplementationB.cs: +# 27| exit get_P3 (abnormal) +#-----| -> exit get_P3 +#-----| -> exit get_P3 + +MultiImplementationA.cs: +# 36| enter M1 +#-----| -> {...} +#-----| -> 0 + +MultiImplementationB.cs: +# 32| enter M1 +#-----| -> {...} +#-----| -> 0 + +MultiImplementationA.cs: +# 36| exit M1 + +MultiImplementationB.cs: +# 32| exit M1 + +MultiImplementationA.cs: +# 36| exit M1 (abnormal) +#-----| -> exit M1 +#-----| -> exit M1 + +MultiImplementationB.cs: +# 32| exit M1 (abnormal) +#-----| -> exit M1 +#-----| -> exit M1 + +MultiImplementationA.cs: +# 36| exit M1 (normal) +#-----| -> exit M1 +#-----| -> exit M1 + +MultiImplementationB.cs: +# 32| exit M1 (normal) +#-----| -> exit M1 +#-----| -> exit M1 + +# 32| 0 +#-----| -> exit M1 (normal) +#-----| -> exit M1 (normal) + +NullCoalescing.cs: +# 3| enter M1 +#-----| -> access to parameter i + +# 3| exit M1 + +# 3| exit M1 (normal) +#-----| -> exit M1 + +# 3| ... ?? ... +#-----| -> exit M1 (normal) + +# 3| access to parameter i +#-----| non-null -> ... ?? ... +#-----| null -> 0 + +# 3| 0 +#-----| -> ... ?? ... + +# 5| enter M2 +#-----| -> access to parameter b + +# 5| exit M2 + +# 5| exit M2 (normal) +#-----| -> exit M2 + +# 5| ... ? ... : ... +#-----| -> exit M2 (normal) + +# 5| [false] ... ?? ... +#-----| false -> 1 + +# 5| [true] ... ?? ... +#-----| true -> 0 + +# 5| access to parameter b +#-----| false -> [false] ... ?? ... +#-----| true -> [true] ... ?? ... +#-----| null -> false + +# 5| false +#-----| false -> [false] ... ?? ... + +# 5| 0 +#-----| -> ... ? ... : ... + +# 5| 1 +#-----| -> ... ? ... : ... + +# 7| enter M3 +#-----| -> access to parameter s1 + +# 7| exit M3 + +# 7| exit M3 (normal) +#-----| -> exit M3 + +# 7| ... ?? ... +#-----| -> exit M3 (normal) + +# 7| access to parameter s1 +#-----| non-null -> ... ?? ... +#-----| null -> access to parameter s2 + +# 7| ... ?? ... +#-----| -> ... ?? ... + +# 7| access to parameter s2 +#-----| non-null -> ... ?? ... +#-----| null -> "" + +# 7| "" +#-----| -> ... ?? ... + +# 9| enter M4 +#-----| -> access to parameter b + +# 9| exit M4 + +# 9| exit M4 (normal) +#-----| -> exit M4 + +# 9| ... ?? ... +#-----| -> exit M4 (normal) + +# 9| [non-null] ... ? ... : ... +#-----| non-null -> ... ?? ... + +# 9| [null] ... ? ... : ... +#-----| null -> "" + +# 9| access to parameter b +#-----| true -> access to parameter s +#-----| false -> access to parameter s + +# 9| access to parameter s +#-----| non-null -> [non-null] ... ? ... : ... +#-----| null -> [null] ... ? ... : ... + +# 9| access to parameter s +#-----| non-null -> [non-null] ... ? ... : ... +#-----| null -> [null] ... ? ... : ... + +# 9| ... ?? ... +#-----| -> ... ?? ... + +# 9| "" +#-----| non-null -> ... ?? ... + +# 11| enter M5 +#-----| -> access to parameter b1 + +# 11| exit M5 + +# 11| exit M5 (normal) +#-----| -> exit M5 + +# 11| ... ? ... : ... +#-----| -> exit M5 (normal) + +# 11| [false] ... ?? ... +#-----| false -> 1 + +# 11| [true] ... ?? ... +#-----| true -> 0 + +# 11| access to parameter b1 +#-----| false -> [false] ... ?? ... +#-----| true -> [true] ... ?? ... +#-----| null -> access to parameter b2 + +# 11| [false] ... && ... +#-----| false -> [false] ... ?? ... + +# 11| [true] ... && ... +#-----| true -> [true] ... ?? ... + +# 11| access to parameter b2 +#-----| false -> [false] ... && ... +#-----| true -> access to parameter b3 + +# 11| access to parameter b3 +#-----| false -> [false] ... && ... +#-----| true -> [true] ... && ... + +# 11| 0 +#-----| -> ... ? ... : ... + +# 11| 1 +#-----| -> ... ? ... : ... + +# 13| enter M6 +#-----| -> {...} + +# 13| exit M6 + +# 13| exit M6 (normal) +#-----| -> exit M6 + +# 14| {...} +#-----| -> ... ...; + +# 15| ... ...; +#-----| -> null + +# 15| Int32 j = ... +#-----| -> ... ...; + +# 15| ... ?? ... +#-----| -> Int32 j = ... + +# 15| (...) ... +#-----| null -> 0 + +# 15| null +#-----| -> (...) ... + +# 15| 0 +#-----| -> ... ?? ... + +# 16| ... ...; +#-----| -> "" + +# 16| String s = ... +#-----| -> ...; + +# 16| ... ?? ... +#-----| -> String s = ... + +# 16| "" +#-----| non-null -> ... ?? ... + +# 17| ...; +#-----| -> access to parameter i + +# 17| ... = ... +#-----| -> exit M6 (normal) + +# 17| ... ?? ... +#-----| -> ... = ... + +# 17| (...) ... +#-----| non-null -> ... ?? ... + +# 17| access to parameter i +#-----| -> (...) ... + +PartialImplementationA.cs: +# 3| enter Partial +#-----| -> call to constructor Object + +# 3| call to constructor Object +#-----| -> this access + +# 3| exit Partial + +# 3| exit Partial (normal) +#-----| -> exit Partial + +# 3| {...} +#-----| -> exit Partial (normal) + +PartialImplementationB.cs: +# 3| ... = ... +#-----| -> this access + +# 3| ... = ... +#-----| -> this access + +# 3| this access +#-----| -> 0 + +# 3| this access +#-----| -> 0 + +# 3| 0 +#-----| -> ... = ... + +# 3| 0 +#-----| -> ... = ... + +# 4| enter Partial +#-----| -> call to constructor Object + +# 4| call to constructor Object +#-----| -> this access + +# 4| exit Partial + +# 4| exit Partial (normal) +#-----| -> exit Partial + +# 4| {...} +#-----| -> exit Partial (normal) + +# 5| access to property P +#-----| -> ... = ... + +# 5| access to property P +#-----| -> ... = ... + +# 5| this access +#-----| -> 0 + +# 5| this access +#-----| -> 0 + +# 5| ... = ... +#-----| -> {...} + +# 5| ... = ... +#-----| -> {...} + +# 5| 0 +#-----| -> access to property P + +# 5| 0 +#-----| -> access to property P + +Patterns.cs: +# 5| enter M1 +#-----| -> {...} + +# 5| exit M1 + +# 5| exit M1 (normal) +#-----| -> exit M1 + +# 6| {...} +#-----| -> ... ...; + +# 7| ... ...; +#-----| -> null + +# 7| Object o = ... +#-----| -> if (...) ... + +# 7| null +#-----| -> Object o = ... + +# 8| if (...) ... +#-----| -> access to local variable o + +# 8| [false] ... is ... +#-----| false -> if (...) ... + +# 8| [true] ... is ... +#-----| true -> {...} + +# 8| access to local variable o +#-----| -> Int32 i1 + +# 8| Int32 i1 +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 9| {...} +#-----| -> ...; + +# 10| ...; +#-----| -> "int " + +# 10| call to method WriteLine +#-----| -> switch (...) {...} + +# 10| $"..." +#-----| -> call to method WriteLine + +# 10| "int " +#-----| -> access to local variable i1 + +# 10| access to local variable i1 +#-----| -> $"..." + +# 12| if (...) ... +#-----| -> access to local variable o + +# 12| [false] ... is ... +#-----| false -> if (...) ... + +# 12| [true] ... is ... +#-----| true -> {...} + +# 12| access to local variable o +#-----| -> String s1 + +# 12| String s1 +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 13| {...} +#-----| -> ...; + +# 14| ...; +#-----| -> "string " + +# 14| call to method WriteLine +#-----| -> switch (...) {...} + +# 14| $"..." +#-----| -> call to method WriteLine + +# 14| "string " +#-----| -> access to local variable s1 + +# 14| access to local variable s1 +#-----| -> $"..." + +# 16| if (...) ... +#-----| -> access to local variable o + +# 16| [false] ... is ... +#-----| false -> switch (...) {...} + +# 16| [true] ... is ... +#-----| true -> {...} + +# 16| access to local variable o +#-----| -> Object v1 + +# 16| Object v1 +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 17| {...} +#-----| -> switch (...) {...} + +# 20| switch (...) {...} +#-----| -> access to local variable o + +# 20| access to local variable o +#-----| -> case ...: + +# 22| case ...: +#-----| -> "xyz" + +# 22| "xyz" +#-----| match -> break; +#-----| no-match -> case ...: + +# 23| break; +#-----| break -> switch (...) {...} + +# 24| case ...: +#-----| -> Int32 i2 + +# 24| Int32 i2 +#-----| no-match -> case ...: +#-----| match -> access to local variable i2 + +# 24| ... > ... +#-----| true -> ...; +#-----| false -> case ...: + +# 24| access to local variable i2 +#-----| -> 0 + +# 24| 0 +#-----| -> ... > ... + +# 25| ...; +#-----| -> "positive " + +# 25| call to method WriteLine +#-----| -> break; + +# 25| $"..." +#-----| -> call to method WriteLine + +# 25| "positive " +#-----| -> access to local variable i2 + +# 25| access to local variable i2 +#-----| -> $"..." + +# 26| break; +#-----| break -> switch (...) {...} + +# 27| case ...: +#-----| -> Int32 i3 + +# 27| Int32 i3 +#-----| match -> ...; +#-----| no-match -> case ...: + +# 28| ...; +#-----| -> "int " + +# 28| call to method WriteLine +#-----| -> break; + +# 28| $"..." +#-----| -> call to method WriteLine + +# 28| "int " +#-----| -> access to local variable i3 + +# 28| access to local variable i3 +#-----| -> $"..." + +# 29| break; +#-----| break -> switch (...) {...} + +# 30| case ...: +#-----| -> String s2 + +# 30| String s2 +#-----| match -> ...; +#-----| no-match -> case ...: + +# 31| ...; +#-----| -> "string " + +# 31| call to method WriteLine +#-----| -> break; + +# 31| $"..." +#-----| -> call to method WriteLine + +# 31| "string " +#-----| -> access to local variable s2 + +# 31| access to local variable s2 +#-----| -> $"..." + +# 32| break; +#-----| break -> switch (...) {...} + +# 33| case ...: +#-----| -> Object v2 + +# 33| Object v2 +#-----| match -> break; +#-----| no-match -> default: + +# 34| break; +#-----| break -> switch (...) {...} + +# 35| default: +#-----| -> ...; + +# 36| ...; +#-----| -> "Something else" + +# 36| call to method WriteLine +#-----| -> break; + +# 36| "Something else" +#-----| -> call to method WriteLine + +# 37| break; +#-----| break -> switch (...) {...} + +# 40| switch (...) {...} +#-----| -> access to local variable o + +# 40| access to local variable o +#-----| -> exit M1 (normal) + +# 47| enter M2 +#-----| -> access to parameter c + +# 47| exit M2 + +# 47| exit M2 (normal) +#-----| -> exit M2 + +# 48| ... is ... +#-----| -> exit M2 (normal) + +# 48| access to parameter c +#-----| -> a + +# 48| not ... +#-----| -> ... is ... + +# 48| a +#-----| -> not ... + +# 50| enter M3 +#-----| -> access to parameter c + +# 50| exit M3 + +# 50| exit M3 (normal) +#-----| -> exit M3 + +# 51| ... ? ... : ... +#-----| -> exit M3 (normal) + +# 51| [false] ... is ... +#-----| false -> access to parameter c + +# 51| [true] ... is ... +#-----| true -> access to parameter c + +# 51| access to parameter c +#-----| -> null + +# 51| [no-match] not ... +#-----| no-match -> [false] ... is ... + +# 51| [match] not ... +#-----| match -> [true] ... is ... + +# 51| null +#-----| match -> [no-match] not ... +#-----| no-match -> [match] not ... + +# 51| ... is ... +#-----| -> ... ? ... : ... + +# 51| access to parameter c +#-----| -> 1 + +# 51| 1 +#-----| -> ... is ... + +# 51| ... is ... +#-----| -> ... ? ... : ... + +# 51| access to parameter c +#-----| -> 2 + +# 51| 2 +#-----| -> ... is ... + +# 53| enter M4 +#-----| -> access to parameter c + +# 53| exit M4 + +# 53| exit M4 (normal) +#-----| -> exit M4 + +# 54| ... is ... +#-----| -> exit M4 (normal) + +# 54| access to parameter c +#-----| -> Patterns u + +# 54| not ... +#-----| -> ... is ... + +# 54| { ... } +#-----| -> not ... + +# 54| Patterns u +#-----| no-match -> { ... } +#-----| match -> 1 + +# 54| [no-match] { ... } +#-----| no-match -> { ... } + +# 54| [match] { ... } +#-----| match -> { ... } + +# 54| 1 +#-----| no-match -> [no-match] { ... } +#-----| match -> [match] { ... } + +# 56| enter M5 +#-----| -> {...} + +# 56| exit M5 + +# 56| exit M5 (normal) +#-----| -> exit M5 + +# 57| {...} +#-----| -> access to parameter i + +# 58| return ...; +#-----| return -> exit M5 (normal) + +# 58| ... switch { ... } +#-----| -> return ...; + +# 58| access to parameter i +#-----| -> 1 + +# 60| ... => ... +#-----| -> ... switch { ... } + +# 60| [no-match] not ... +#-----| no-match -> _ + +# 60| [match] not ... +#-----| match -> "not 1" + +# 60| 1 +#-----| match -> [no-match] not ... +#-----| no-match -> [match] not ... + +# 60| "not 1" +#-----| -> ... => ... + +# 61| ... => ... +#-----| -> ... switch { ... } + +# 61| _ +#-----| match -> "other" + +# 61| "other" +#-----| -> ... => ... + +# 65| enter M6 +#-----| -> {...} + +# 65| exit M6 + +# 65| exit M6 (normal) +#-----| -> exit M6 + +# 66| {...} +#-----| -> 2 + +# 67| return ...; +#-----| return -> exit M6 (normal) + +# 67| ... switch { ... } +#-----| -> return ...; + +# 67| 2 +#-----| -> 2 + +# 69| [no-match] not ... +#-----| no-match -> 2 + +# 69| 2 +#-----| match -> [no-match] not ... + +# 70| ... => ... +#-----| -> ... switch { ... } + +# 70| 2 +#-----| match -> "possible" + +# 70| "possible" +#-----| -> ... => ... + +# 74| enter M7 +#-----| -> {...} + +# 74| exit M7 + +# 74| exit M7 (normal) +#-----| -> exit M7 + +# 75| {...} +#-----| -> access to parameter i + +# 76| return ...; +#-----| return -> exit M7 (normal) + +# 76| ... switch { ... } +#-----| -> return ...; + +# 76| access to parameter i +#-----| -> 1 + +# 78| ... => ... +#-----| -> ... switch { ... } + +# 78| > ... +#-----| match -> "> 1" +#-----| no-match -> 0 + +# 78| 1 +#-----| -> > ... + +# 78| "> 1" +#-----| -> ... => ... + +# 79| ... => ... +#-----| -> ... switch { ... } + +# 79| < ... +#-----| match -> "< 0" +#-----| no-match -> 1 + +# 79| 0 +#-----| -> < ... + +# 79| "< 0" +#-----| -> ... => ... + +# 80| ... => ... +#-----| -> ... switch { ... } + +# 80| 1 +#-----| match -> "1" +#-----| no-match -> _ + +# 80| "1" +#-----| -> ... => ... + +# 81| ... => ... +#-----| -> ... switch { ... } + +# 81| _ +#-----| match -> "0" + +# 81| "0" +#-----| -> ... => ... + +# 85| enter M8 +#-----| -> access to parameter i + +# 85| exit M8 + +# 85| exit M8 (normal) +#-----| -> exit M8 + +# 85| ... ? ... : ... +#-----| -> exit M8 (normal) + +# 85| [false] ... is ... +#-----| false -> "2" + +# 85| [true] ... is ... +#-----| true -> "not 2" + +# 85| access to parameter i +#-----| -> 1 + +# 85| [no-match] ... or ... +#-----| no-match -> [false] ... is ... + +# 85| [match] ... or ... +#-----| match -> [true] ... is ... + +# 85| 1 +#-----| match -> [match] ... or ... +#-----| no-match -> 2 + +# 85| [no-match] not ... +#-----| no-match -> [no-match] ... or ... + +# 85| [match] not ... +#-----| match -> [match] ... or ... + +# 85| 2 +#-----| match -> [no-match] not ... +#-----| no-match -> [match] not ... + +# 85| "not 2" +#-----| -> ... ? ... : ... + +# 85| "2" +#-----| -> ... ? ... : ... + +# 87| enter M9 +#-----| -> access to parameter i + +# 87| exit M9 + +# 87| exit M9 (normal) +#-----| -> exit M9 + +# 87| ... ? ... : ... +#-----| -> exit M9 (normal) + +# 87| [false] ... is ... +#-----| false -> "not 1" + +# 87| [true] ... is ... +#-----| true -> "1" + +# 87| access to parameter i +#-----| -> 1 + +# 87| [no-match] ... and ... +#-----| no-match -> [false] ... is ... + +# 87| [match] ... and ... +#-----| match -> [true] ... is ... + +# 87| 1 +#-----| no-match -> [no-match] ... and ... +#-----| match -> 2 + +# 87| [no-match] not ... +#-----| no-match -> [no-match] ... and ... + +# 87| [match] not ... +#-----| match -> [match] ... and ... + +# 87| 2 +#-----| match -> [no-match] not ... +#-----| no-match -> [match] not ... + +# 87| "1" +#-----| -> ... ? ... : ... + +# 87| "not 1" +#-----| -> ... ? ... : ... + +# 93| enter M10 +#-----| -> {...} + +# 93| exit M10 + +# 93| exit M10 (normal) +#-----| -> exit M10 + +# 94| {...} +#-----| -> if (...) ... + +# 95| if (...) ... +#-----| -> this access + +# 95| [false] ... is ... +#-----| false -> exit M10 (normal) + +# 95| [true] ... is ... +#-----| true -> {...} + +# 95| this access +#-----| -> access to constant A + +# 95| [no-match] { ... } +#-----| no-match -> [false] ... is ... + +# 95| [match] { ... } +#-----| match -> [true] ... is ... + +# 95| [no-match] { ... } +#-----| no-match -> [no-match] { ... } + +# 95| [match] { ... } +#-----| match -> [match] { ... } + +# 95| [no-match] ... or ... +#-----| no-match -> [no-match] { ... } + +# 95| [match] ... or ... +#-----| match -> [match] { ... } + +# 95| access to constant A +#-----| match -> [match] ... or ... +#-----| no-match -> access to constant B + +# 95| access to constant B +#-----| no-match -> [no-match] ... or ... +#-----| match -> [match] ... or ... + +# 96| {...} +#-----| -> ...; + +# 97| ...; +#-----| -> "not C" + +# 97| call to method WriteLine +#-----| -> exit M10 (normal) + +# 97| "not C" +#-----| -> call to method WriteLine + +PostDominance.cs: +# 5| enter M1 +#-----| -> {...} + +# 5| exit M1 + +# 5| exit M1 (normal) +#-----| -> exit M1 + +# 6| {...} +#-----| -> ...; + +# 7| ...; +#-----| -> access to parameter s + +# 7| call to method WriteLine +#-----| -> exit M1 (normal) + +# 7| access to parameter s +#-----| -> call to method WriteLine + +# 10| enter M2 +#-----| -> {...} + +# 10| exit M2 + +# 10| exit M2 (normal) +#-----| -> exit M2 + +# 11| {...} +#-----| -> if (...) ... + +# 12| if (...) ... +#-----| -> access to parameter s + +# 12| [false] ... is ... +#-----| false -> ...; + +# 12| [true] ... is ... +#-----| true -> return ...; + +# 12| access to parameter s +#-----| -> null + +# 12| null +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 13| return ...; +#-----| return -> exit M2 (normal) + +# 14| ...; +#-----| -> access to parameter s + +# 14| call to method WriteLine +#-----| -> exit M2 (normal) + +# 14| access to parameter s +#-----| -> call to method WriteLine + +# 17| enter M3 +#-----| -> {...} + +# 17| exit M3 + +# 17| exit M3 (abnormal) +#-----| -> exit M3 + +# 17| exit M3 (normal) +#-----| -> exit M3 + +# 18| {...} +#-----| -> if (...) ... + +# 19| if (...) ... +#-----| -> access to parameter s + +# 19| [false] ... is ... +#-----| false -> ...; + +# 19| [true] ... is ... +#-----| true -> nameof(...) + +# 19| access to parameter s +#-----| -> null + +# 19| null +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 20| throw ...; +#-----| exception(ArgumentNullException) -> exit M3 (abnormal) + +# 20| object creation of type ArgumentNullException +#-----| -> throw ...; + +# 20| nameof(...) +#-----| -> object creation of type ArgumentNullException + +# 21| ...; +#-----| -> access to parameter s + +# 21| call to method WriteLine +#-----| -> exit M3 (normal) + +# 21| access to parameter s +#-----| -> call to method WriteLine + +Qualifiers.cs: +# 7| enter Method +#-----| -> null + +# 7| exit Method + +# 7| exit Method (normal) +#-----| -> exit Method + +# 7| null +#-----| -> exit Method (normal) + +# 8| enter StaticMethod +#-----| -> null + +# 8| exit StaticMethod + +# 8| exit StaticMethod (normal) +#-----| -> exit StaticMethod + +# 8| null +#-----| -> exit StaticMethod (normal) + +# 10| enter M +#-----| -> {...} + +# 10| exit M + +# 10| exit M (normal) +#-----| -> exit M + +# 11| {...} +#-----| -> ... ...; + +# 12| ... ...; +#-----| -> this access + +# 12| Qualifiers q = ... +#-----| -> ...; + +# 12| access to field Field +#-----| -> Qualifiers q = ... + +# 12| this access +#-----| -> access to field Field + +# 13| ...; +#-----| -> this access + +# 13| ... = ... +#-----| -> ...; + +# 13| access to property Property +#-----| -> ... = ... + +# 13| this access +#-----| -> access to property Property + +# 14| ...; +#-----| -> this access + +# 14| ... = ... +#-----| -> ...; + +# 14| call to method Method +#-----| -> ... = ... + +# 14| this access +#-----| -> call to method Method + +# 16| ...; +#-----| -> this access + +# 16| ... = ... +#-----| -> ...; + +# 16| access to field Field +#-----| -> ... = ... + +# 16| this access +#-----| -> access to field Field + +# 17| ...; +#-----| -> this access + +# 17| ... = ... +#-----| -> ...; + +# 17| access to property Property +#-----| -> ... = ... + +# 17| this access +#-----| -> access to property Property + +# 18| ...; +#-----| -> this access + +# 18| ... = ... +#-----| -> ...; + +# 18| call to method Method +#-----| -> ... = ... + +# 18| this access +#-----| -> call to method Method + +# 20| ...; +#-----| -> access to field StaticField + +# 20| ... = ... +#-----| -> ...; + +# 20| access to field StaticField +#-----| -> ... = ... + +# 21| ...; +#-----| -> access to property StaticProperty + +# 21| ... = ... +#-----| -> ...; + +# 21| access to property StaticProperty +#-----| -> ... = ... + +# 22| ...; +#-----| -> call to method StaticMethod + +# 22| ... = ... +#-----| -> ...; + +# 22| call to method StaticMethod +#-----| -> ... = ... + +# 24| ...; +#-----| -> access to field StaticField + +# 24| ... = ... +#-----| -> ...; + +# 24| access to field StaticField +#-----| -> ... = ... + +# 25| ...; +#-----| -> access to property StaticProperty + +# 25| ... = ... +#-----| -> ...; + +# 25| access to property StaticProperty +#-----| -> ... = ... + +# 26| ...; +#-----| -> call to method StaticMethod + +# 26| ... = ... +#-----| -> ...; + +# 26| call to method StaticMethod +#-----| -> ... = ... + +# 28| ...; +#-----| -> access to field StaticField + +# 28| ... = ... +#-----| -> ...; + +# 28| access to field Field +#-----| -> ... = ... + +# 28| access to field StaticField +#-----| -> access to field Field + +# 29| ...; +#-----| -> access to property StaticProperty + +# 29| ... = ... +#-----| -> ...; + +# 29| access to property Property +#-----| -> ... = ... + +# 29| access to property StaticProperty +#-----| -> access to property Property + +# 30| ...; +#-----| -> call to method StaticMethod + +# 30| ... = ... +#-----| -> exit M (normal) + +# 30| call to method Method +#-----| -> ... = ... + +# 30| call to method StaticMethod +#-----| -> call to method Method + +Switch.cs: +# 5| enter M1 +#-----| -> {...} + +# 5| exit M1 + +# 5| exit M1 (normal) +#-----| -> exit M1 + +# 6| {...} +#-----| -> switch (...) {...} + +# 7| switch (...) {...} +#-----| -> access to parameter o + +# 7| access to parameter o +#-----| -> exit M1 (normal) + +# 10| enter M2 +#-----| -> {...} + +# 10| exit M2 + +# 10| exit M2 (abnormal) +#-----| -> exit M2 + +# 10| exit M2 (normal) +#-----| -> exit M2 + +# 11| {...} +#-----| -> switch (...) {...} + +# 12| switch (...) {...} +#-----| -> access to parameter o + +# 12| access to parameter o +#-----| -> case ...: + +# 14| case ...: +#-----| -> "a" + +# 14| "a" +#-----| match -> return ...; +#-----| no-match -> case ...: + +# 15| return ...; +#-----| return -> exit M2 (normal) + +# 16| case ...: +#-----| -> 0 + +# 16| 0 +#-----| match -> object creation of type Exception +#-----| no-match -> case ...: + +# 17| throw ...; +#-----| exception(Exception) -> exit M2 (abnormal) + +# 17| object creation of type Exception +#-----| -> throw ...; + +# 18| case ...: +#-----| -> null + +# 18| null +#-----| match -> goto default; +#-----| no-match -> case ...: + +# 19| goto default; +#-----| goto(default) -> default: + +# 20| case ...: +#-----| -> Int32 i + +# 20| Int32 i +#-----| match -> if (...) ... +#-----| no-match -> case ...: + +# 21| if (...) ... +#-----| -> access to parameter o + +# 21| ... == ... +#-----| true -> return ...; +#-----| false -> 0 + +# 21| access to parameter o +#-----| -> null + +# 21| null +#-----| -> ... == ... + +# 22| return ...; +#-----| return -> exit M2 (normal) + +# 23| goto case ...; +#-----| goto(0) -> case ...: + +# 23| 0 +#-----| -> goto case ...; + +# 24| case ...: +#-----| -> String s + +# 24| String s +#-----| no-match -> case ...: +#-----| match -> access to local variable s + +# 24| [false] ... && ... +#-----| false -> case ...: + +# 24| [true] ... && ... +#-----| true -> ...; + +# 24| ... > ... +#-----| false -> [false] ... && ... +#-----| true -> access to local variable s + +# 24| access to property Length +#-----| -> 0 + +# 24| access to local variable s +#-----| -> access to property Length + +# 24| 0 +#-----| -> ... > ... + +# 24| ... != ... +#-----| false -> [false] ... && ... +#-----| true -> [true] ... && ... + +# 24| access to local variable s +#-----| -> "a" + +# 24| "a" +#-----| -> ... != ... + +# 25| ...; +#-----| -> access to local variable s + +# 25| call to method WriteLine +#-----| -> return ...; + +# 25| access to local variable s +#-----| -> call to method WriteLine + +# 26| return ...; +#-----| return -> exit M2 (normal) + +# 27| case ...: +#-----| -> Double d + +# 27| Double d +#-----| match -> call to method Throw +#-----| no-match -> default: + +# 27| call to method Throw +#-----| exception(Exception) -> exit M2 (abnormal) + +# 28| Label: +#-----| -> return ...; + +# 29| return ...; +#-----| return -> exit M2 (normal) + +# 30| default: +#-----| -> goto ...; + +# 31| goto ...; +#-----| goto(Label) -> Label: + +# 35| enter M3 +#-----| -> {...} + +# 35| exit M3 + +# 35| exit M3 (abnormal) +#-----| -> exit M3 + +# 36| {...} +#-----| -> switch (...) {...} + +# 37| switch (...) {...} +#-----| -> call to method Throw + +# 37| call to method Throw +#-----| exception(Exception) -> exit M3 (abnormal) + +# 44| enter M4 +#-----| -> {...} + +# 44| exit M4 + +# 44| exit M4 (normal) +#-----| -> exit M4 + +# 45| {...} +#-----| -> switch (...) {...} + +# 46| switch (...) {...} +#-----| -> access to parameter o + +# 46| access to parameter o +#-----| -> case ...: + +# 48| case ...: +#-----| -> access to type Int32 + +# 48| access to type Int32 +#-----| match -> break; +#-----| no-match -> case ...: + +# 49| break; +#-----| break -> exit M4 (normal) + +# 50| case ...: +#-----| -> access to type Boolean + +# 50| access to type Boolean +#-----| match -> access to parameter o +#-----| no-match -> exit M4 (normal) + +# 50| ... != ... +#-----| true -> break; +#-----| false -> exit M4 (normal) + +# 50| access to parameter o +#-----| -> null + +# 50| null +#-----| -> ... != ... + +# 51| break; +#-----| break -> exit M4 (normal) + +# 55| enter M5 +#-----| -> {...} + +# 55| exit M5 + +# 55| exit M5 (normal) +#-----| -> exit M5 + +# 56| {...} +#-----| -> switch (...) {...} + +# 57| switch (...) {...} +#-----| -> 1 + +# 57| ... + ... +#-----| -> case ...: + +# 57| 1 +#-----| -> 2 + +# 57| 2 +#-----| -> ... + ... + +# 59| case ...: +#-----| -> 2 + +# 59| 2 +#-----| no-match -> case ...: + +# 61| case ...: +#-----| -> 3 + +# 61| 3 +#-----| match -> break; + +# 62| break; +#-----| break -> exit M5 (normal) + +# 66| enter M6 +#-----| -> {...} + +# 66| exit M6 + +# 66| exit M6 (normal) +#-----| -> exit M6 + +# 67| {...} +#-----| -> switch (...) {...} + +# 68| switch (...) {...} +#-----| -> access to parameter s + +# 68| (...) ... +#-----| -> case ...: + +# 68| access to parameter s +#-----| -> (...) ... + +# 70| case ...: +#-----| -> access to type Int32 + +# 70| access to type Int32 +#-----| no-match -> case ...: + +# 72| case ...: +#-----| -> "" + +# 72| "" +#-----| match -> break; +#-----| no-match -> exit M6 (normal) + +# 73| break; +#-----| break -> exit M6 (normal) + +# 77| enter M7 +#-----| -> {...} + +# 77| exit M7 + +# 77| exit M7 (normal) +#-----| -> exit M7 + +# 78| {...} +#-----| -> switch (...) {...} + +# 79| switch (...) {...} +#-----| -> access to parameter i + +# 79| access to parameter i +#-----| -> case ...: + +# 81| case ...: +#-----| -> 1 + +# 81| 1 +#-----| match -> true +#-----| no-match -> case ...: + +# 82| return ...; +#-----| return -> exit M7 (normal) + +# 82| true +#-----| -> return ...; + +# 83| case ...: +#-----| -> 2 + +# 83| 2 +#-----| match -> if (...) ... +#-----| no-match -> false + +# 84| if (...) ... +#-----| -> access to parameter j + +# 84| ... > ... +#-----| true -> break; +#-----| false -> true + +# 84| access to parameter j +#-----| -> 2 + +# 84| 2 +#-----| -> ... > ... + +# 85| break; +#-----| break -> false + +# 86| return ...; +#-----| return -> exit M7 (normal) + +# 86| true +#-----| -> return ...; + +# 88| return ...; +#-----| return -> exit M7 (normal) + +# 88| false +#-----| -> return ...; + +# 91| enter M8 +#-----| -> {...} + +# 91| exit M8 + +# 91| exit M8 (normal) +#-----| -> exit M8 + +# 92| {...} +#-----| -> switch (...) {...} + +# 93| switch (...) {...} +#-----| -> access to parameter o + +# 93| access to parameter o +#-----| -> case ...: + +# 95| case ...: +#-----| -> access to type Int32 + +# 95| access to type Int32 +#-----| match -> true +#-----| no-match -> false + +# 96| return ...; +#-----| return -> exit M8 (normal) + +# 96| true +#-----| -> return ...; + +# 98| return ...; +#-----| return -> exit M8 (normal) + +# 98| false +#-----| -> return ...; + +# 101| enter M9 +#-----| -> {...} + +# 101| exit M9 + +# 101| exit M9 (normal) +#-----| -> exit M9 + +# 102| {...} +#-----| -> switch (...) {...} + +# 103| switch (...) {...} +#-----| -> access to parameter s + +# 103| access to parameter s +#-----| non-null -> access to property Length +#-----| null -> case ...: + +# 103| access to property Length +#-----| -> case ...: + +# 105| case ...: +#-----| -> 0 + +# 105| 0 +#-----| match -> 0 +#-----| no-match -> case ...: + +# 105| return ...; +#-----| return -> exit M9 (normal) + +# 105| 0 +#-----| -> return ...; + +# 106| case ...: +#-----| -> 1 + +# 106| 1 +#-----| match -> 1 +#-----| no-match -> 1 + +# 106| return ...; +#-----| return -> exit M9 (normal) + +# 106| 1 +#-----| -> return ...; + +# 108| return ...; +#-----| return -> exit M9 (normal) + +# 108| -... +#-----| -> return ...; + +# 108| 1 +#-----| -> -... + +# 111| enter Throw +#-----| -> object creation of type Exception + +# 111| exit Throw + +# 111| exit Throw (abnormal) +#-----| -> exit Throw + +# 111| throw ... +#-----| exception(Exception) -> exit Throw (abnormal) + +# 111| object creation of type Exception +#-----| -> throw ... + +# 113| enter M10 +#-----| -> {...} + +# 113| exit M10 + +# 113| exit M10 (normal) +#-----| -> exit M10 + +# 114| {...} +#-----| -> switch (...) {...} + +# 115| switch (...) {...} +#-----| -> access to parameter s + +# 115| access to property Length +#-----| -> case ...: + +# 115| access to parameter s +#-----| -> access to property Length + +# 117| case ...: +#-----| -> 3 + +# 117| 3 +#-----| no-match -> case ...: +#-----| match -> access to parameter s + +# 117| ... == ... +#-----| true -> 1 +#-----| false -> case ...: + +# 117| access to parameter s +#-----| -> "foo" + +# 117| "foo" +#-----| -> ... == ... + +# 117| return ...; +#-----| return -> exit M10 (normal) + +# 117| 1 +#-----| -> return ...; + +# 118| case ...: +#-----| -> 2 + +# 118| 2 +#-----| no-match -> 1 +#-----| match -> access to parameter s + +# 118| ... == ... +#-----| true -> 2 +#-----| false -> 1 + +# 118| access to parameter s +#-----| -> "fu" + +# 118| "fu" +#-----| -> ... == ... + +# 118| return ...; +#-----| return -> exit M10 (normal) + +# 118| 2 +#-----| -> return ...; + +# 120| return ...; +#-----| return -> exit M10 (normal) + +# 120| -... +#-----| -> return ...; + +# 120| 1 +#-----| -> -... + +# 123| enter M11 +#-----| -> {...} + +# 123| exit M11 + +# 123| exit M11 (normal) +#-----| -> exit M11 + +# 124| {...} +#-----| -> if (...) ... + +# 125| if (...) ... +#-----| -> access to parameter o + +# 125| [false] ... switch { ... } +#-----| false -> exit M11 (normal) + +# 125| [true] ... switch { ... } +#-----| true -> return ...; + +# 125| access to parameter o +#-----| -> Boolean b + +# 125| [false] ... => ... +#-----| false -> [false] ... switch { ... } + +# 125| [true] ... => ... +#-----| true -> [true] ... switch { ... } + +# 125| Boolean b +#-----| match -> access to local variable b +#-----| no-match -> _ + +# 125| access to local variable b +#-----| false -> [false] ... => ... +#-----| true -> [true] ... => ... + +# 125| [false] ... => ... +#-----| false -> [false] ... switch { ... } + +# 125| _ +#-----| match -> false + +# 125| false +#-----| false -> [false] ... => ... + +# 126| return ...; +#-----| return -> exit M11 (normal) + +# 129| enter M12 +#-----| -> {...} + +# 129| exit M12 + +# 129| exit M12 (normal) +#-----| -> exit M12 + +# 130| {...} +#-----| -> access to parameter o + +# 131| return ...; +#-----| return -> exit M12 (normal) + +# 131| [non-null] ... switch { ... } +#-----| non-null -> call to method ToString + +# 131| [null] ... switch { ... } +#-----| null -> return ...; + +# 131| access to parameter o +#-----| -> String s + +# 131| [non-null] ... => ... +#-----| non-null -> [non-null] ... switch { ... } + +# 131| [null] ... => ... +#-----| null -> [null] ... switch { ... } + +# 131| String s +#-----| match -> access to local variable s +#-----| no-match -> _ + +# 131| access to local variable s +#-----| non-null -> [non-null] ... => ... +#-----| null -> [null] ... => ... + +# 131| [null] ... => ... +#-----| null -> [null] ... switch { ... } + +# 131| _ +#-----| match -> null + +# 131| null +#-----| null -> [null] ... => ... + +# 131| call to method ToString +#-----| -> return ...; + +# 134| enter M13 +#-----| -> {...} + +# 134| exit M13 + +# 134| exit M13 (normal) +#-----| -> exit M13 + +# 135| {...} +#-----| -> switch (...) {...} + +# 136| switch (...) {...} +#-----| -> access to parameter i + +# 136| access to parameter i +#-----| -> case ...: + +# 138| default: +#-----| -> 1 + +# 138| return ...; +#-----| return -> exit M13 (normal) + +# 138| -... +#-----| -> return ...; + +# 138| 1 +#-----| -> -... + +# 139| case ...: +#-----| -> 1 + +# 139| 1 +#-----| match -> 1 +#-----| no-match -> case ...: + +# 139| return ...; +#-----| return -> exit M13 (normal) + +# 139| 1 +#-----| -> return ...; + +# 140| case ...: +#-----| -> 2 + +# 140| 2 +#-----| no-match -> default: +#-----| match -> 2 + +# 140| return ...; +#-----| return -> exit M13 (normal) + +# 140| 2 +#-----| -> return ...; + +# 144| enter M14 +#-----| -> {...} + +# 144| exit M14 + +# 144| exit M14 (normal) +#-----| -> exit M14 + +# 145| {...} +#-----| -> switch (...) {...} + +# 146| switch (...) {...} +#-----| -> access to parameter i + +# 146| access to parameter i +#-----| -> case ...: + +# 148| case ...: +#-----| -> 1 + +# 148| 1 +#-----| match -> 1 +#-----| no-match -> case ...: + +# 148| return ...; +#-----| return -> exit M14 (normal) + +# 148| 1 +#-----| -> return ...; + +# 149| default: +#-----| -> 1 + +# 149| return ...; +#-----| return -> exit M14 (normal) + +# 149| -... +#-----| -> return ...; + +# 149| 1 +#-----| -> -... + +# 150| case ...: +#-----| -> 2 + +# 150| 2 +#-----| no-match -> default: +#-----| match -> 2 + +# 150| return ...; +#-----| return -> exit M14 (normal) + +# 150| 2 +#-----| -> return ...; + +# 154| enter M15 +#-----| -> {...} + +# 154| exit M15 + +# 154| exit M15 (abnormal) +#-----| -> exit M15 + +# 154| exit M15 (normal) +#-----| -> exit M15 + +# 155| {...} +#-----| -> ... ...; + +# 156| ... ...; +#-----| -> access to parameter b + +# 156| String s = ... +#-----| -> if (...) ... + +# 156| ... switch { ... } +#-----| -> String s = ... + +# 156| access to parameter b +#-----| -> true + +# 156| ... => ... +#-----| -> ... switch { ... } + +# 156| true +#-----| match -> "a" +#-----| no-match -> false + +# 156| "a" +#-----| -> ... => ... + +# 156| ... => ... +#-----| -> ... switch { ... } + +# 156| false +#-----| match -> "b" +#-----| exception(InvalidOperationException) -> exit M15 (abnormal) + +# 156| "b" +#-----| -> ... => ... + +# 157| if (...) ... +#-----| -> access to parameter b + +# 157| access to parameter b +#-----| true -> ...; +#-----| false -> ...; + +# 158| ...; +#-----| -> "a = " + +# 158| call to method WriteLine +#-----| -> exit M15 (normal) + +# 158| $"..." +#-----| -> call to method WriteLine + +# 158| "a = " +#-----| -> access to local variable s + +# 158| access to local variable s +#-----| -> $"..." + +# 160| ...; +#-----| -> "b = " + +# 160| call to method WriteLine +#-----| -> exit M15 (normal) + +# 160| $"..." +#-----| -> call to method WriteLine + +# 160| "b = " +#-----| -> access to local variable s + +# 160| access to local variable s +#-----| -> $"..." + +TypeAccesses.cs: +# 3| enter M +#-----| -> {...} + +# 3| exit M + +# 3| exit M (normal) +#-----| -> exit M + +# 4| {...} +#-----| -> ... ...; + +# 5| ... ...; +#-----| -> access to parameter o + +# 5| String s = ... +#-----| -> ...; + +# 5| (...) ... +#-----| -> String s = ... + +# 5| access to parameter o +#-----| -> (...) ... + +# 6| ...; +#-----| -> access to parameter o + +# 6| ... = ... +#-----| -> if (...) ... + +# 6| ... as ... +#-----| -> ... = ... + +# 6| access to parameter o +#-----| -> ... as ... + +# 7| if (...) ... +#-----| -> access to parameter o + +# 7| [false] ... is ... +#-----| false -> ... ...; + +# 7| [true] ... is ... +#-----| true -> ; + +# 7| access to parameter o +#-----| -> Int32 j + +# 7| Int32 j +#-----| no-match -> [false] ... is ... +#-----| match -> [true] ... is ... + +# 7| ; +#-----| -> ... ...; + +# 8| ... ...; +#-----| -> typeof(...) + +# 8| Type t = ... +#-----| -> exit M (normal) + +# 8| typeof(...) +#-----| -> Type t = ... + +VarDecls.cs: +# 5| enter M1 +#-----| -> {...} + +# 5| exit M1 + +# 5| exit M1 (normal) +#-----| -> exit M1 + +# 6| {...} +#-----| -> fixed(...) { ... } + +# 7| fixed(...) { ... } +#-----| -> access to parameter strings + +# 7| Char* c1 = ... +#-----| -> access to parameter strings + +# 7| (...) ... +#-----| -> Char* c1 = ... + +# 7| access to array element +#-----| -> (...) ... + +# 7| access to parameter strings +#-----| -> 0 + +# 7| 0 +#-----| -> access to array element + +# 7| Char* c2 = ... +#-----| -> {...} + +# 7| (...) ... +#-----| -> Char* c2 = ... + +# 7| access to array element +#-----| -> (...) ... + +# 7| access to parameter strings +#-----| -> 1 + +# 7| 1 +#-----| -> access to array element + +# 8| {...} +#-----| -> access to local variable c1 + +# 9| return ...; +#-----| return -> exit M1 (normal) + +# 9| (...) ... +#-----| -> return ...; + +# 9| access to local variable c1 +#-----| -> (...) ... + +# 13| enter M2 +#-----| -> {...} + +# 13| exit M2 + +# 13| exit M2 (normal) +#-----| -> exit M2 + +# 14| {...} +#-----| -> ... ...; + +# 15| ... ...; +#-----| -> access to parameter s + +# 15| String s1 = ... +#-----| -> access to parameter s + +# 15| access to parameter s +#-----| -> String s1 = ... + +# 15| String s2 = ... +#-----| -> access to local variable s1 + +# 15| access to parameter s +#-----| -> String s2 = ... + +# 16| return ...; +#-----| return -> exit M2 (normal) + +# 16| ... + ... +#-----| -> return ...; + +# 16| access to local variable s1 +#-----| -> access to local variable s2 + +# 16| access to local variable s2 +#-----| -> ... + ... + +# 19| enter M3 +#-----| -> {...} + +# 19| exit M3 + +# 19| exit M3 (normal) +#-----| -> exit M3 + +# 20| {...} +#-----| -> using (...) {...} + +# 21| using (...) {...} +#-----| -> object creation of type C + +# 21| object creation of type C +#-----| -> ; + +# 22| ; +#-----| -> using (...) {...} + +# 24| using (...) {...} +#-----| -> object creation of type C + +# 24| C x = ... +#-----| -> object creation of type C + +# 24| object creation of type C +#-----| -> C x = ... + +# 24| C y = ... +#-----| -> access to parameter b + +# 24| object creation of type C +#-----| -> C y = ... + +# 25| return ...; +#-----| return -> exit M3 (normal) + +# 25| ... ? ... : ... +#-----| -> return ...; + +# 25| access to parameter b +#-----| true -> access to local variable x +#-----| false -> access to local variable y + +# 25| access to local variable x +#-----| -> ... ? ... : ... + +# 25| access to local variable y +#-----| -> ... ? ... : ... + +# 28| enter Dispose +#-----| -> {...} + +# 28| exit Dispose + +# 28| exit Dispose (normal) +#-----| -> exit Dispose + +# 28| {...} +#-----| -> exit Dispose (normal) + +cflow.cs: +# 5| enter Main +#-----| -> {...} + +# 5| exit Main + +# 5| exit Main (normal) +#-----| -> exit Main + +# 6| {...} +#-----| -> ... ...; + +# 7| ... ...; +#-----| -> access to parameter args + +# 7| Int32 a = ... +#-----| -> ...; + +# 7| access to property Length +#-----| -> Int32 a = ... + +# 7| access to parameter args +#-----| -> access to property Length + +# 9| ...; +#-----| -> object creation of type ControlFlow + +# 9| ... = ... +#-----| -> if (...) ... + +# 9| call to method Switch +#-----| -> ... = ... + +# 9| object creation of type ControlFlow +#-----| -> access to local variable a + +# 9| access to local variable a +#-----| -> call to method Switch + +# 11| if (...) ... +#-----| -> access to local variable a + +# 11| ... > ... +#-----| true -> ...; +#-----| false -> while (...) ... + +# 11| access to local variable a +#-----| -> 3 + +# 11| 3 +#-----| -> ... > ... + +# 12| ...; +#-----| -> "more than a few" + +# 12| call to method WriteLine +#-----| -> while (...) ... + +# 12| "more than a few" +#-----| -> call to method WriteLine + +# 14| while (...) ... +#-----| -> access to local variable a + +# 14| ... > ... +#-----| true -> {...} +#-----| false -> do ... while (...); + +# 14| access to local variable a +#-----| -> 0 + +# 14| 0 +#-----| -> ... > ... + +# 15| {...} +#-----| -> ...; + +# 16| ...; +#-----| -> access to local variable a + +# 16| call to method WriteLine +#-----| -> access to local variable a + +# 16| ... * ... +#-----| -> call to method WriteLine + +# 16| ...-- +#-----| -> 100 + +# 16| access to local variable a +#-----| -> ...-- + +# 16| 100 +#-----| -> ... * ... + +# 19| do ... while (...); +#-----| -> {...} + +# 20| {...} +#-----| -> ...; + +# 21| ...; +#-----| -> access to local variable a + +# 21| call to method WriteLine +#-----| -> access to local variable a + +# 21| -... +#-----| -> call to method WriteLine + +# 21| ...++ +#-----| -> -... + +# 21| access to local variable a +#-----| -> ...++ + +# 22| ... < ... +#-----| true -> {...} +#-----| false -> for (...;...;...) ... + +# 22| access to local variable a +#-----| -> 10 + +# 22| 10 +#-----| -> ... < ... + +# 24| for (...;...;...) ... +#-----| -> 1 + +# 24| Int32 i = ... +#-----| -> access to local variable i + +# 24| 1 +#-----| -> Int32 i = ... + +# 24| ... <= ... +#-----| true -> {...} +#-----| false -> exit Main (normal) + +# 24| access to local variable i +#-----| -> 20 + +# 24| 20 +#-----| -> ... <= ... + +# 24| ...++ +#-----| -> access to local variable i + +# 24| access to local variable i +#-----| -> ...++ + +# 25| {...} +#-----| -> if (...) ... + +# 26| if (...) ... +#-----| -> access to local variable i + +# 26| [false] ... && ... +#-----| false -> if (...) ... + +# 26| [true] ... && ... +#-----| true -> ...; + +# 26| ... == ... +#-----| false -> [false] ... && ... +#-----| true -> access to local variable i + +# 26| ... % ... +#-----| -> 0 + +# 26| access to local variable i +#-----| -> 3 + +# 26| 3 +#-----| -> ... % ... + +# 26| 0 +#-----| -> ... == ... + +# 26| ... == ... +#-----| false -> [false] ... && ... +#-----| true -> [true] ... && ... + +# 26| ... % ... +#-----| -> 0 + +# 26| access to local variable i +#-----| -> 5 + +# 26| 5 +#-----| -> ... % ... + +# 26| 0 +#-----| -> ... == ... + +# 27| ...; +#-----| -> "FizzBuzz" + +# 27| call to method WriteLine +#-----| -> access to local variable i + +# 27| "FizzBuzz" +#-----| -> call to method WriteLine + +# 28| if (...) ... +#-----| -> access to local variable i + +# 28| ... == ... +#-----| true -> ...; +#-----| false -> if (...) ... + +# 28| ... % ... +#-----| -> 0 + +# 28| access to local variable i +#-----| -> 3 + +# 28| 3 +#-----| -> ... % ... + +# 28| 0 +#-----| -> ... == ... + +# 29| ...; +#-----| -> "Fizz" + +# 29| call to method WriteLine +#-----| -> access to local variable i + +# 29| "Fizz" +#-----| -> call to method WriteLine + +# 30| if (...) ... +#-----| -> access to local variable i + +# 30| ... == ... +#-----| true -> ...; +#-----| false -> ...; + +# 30| ... % ... +#-----| -> 0 + +# 30| access to local variable i +#-----| -> 5 + +# 30| 5 +#-----| -> ... % ... + +# 30| 0 +#-----| -> ... == ... + +# 31| ...; +#-----| -> "Buzz" + +# 31| call to method WriteLine +#-----| -> access to local variable i + +# 31| "Buzz" +#-----| -> call to method WriteLine + +# 33| ...; +#-----| -> access to local variable i + +# 33| call to method WriteLine +#-----| -> access to local variable i + +# 33| access to local variable i +#-----| -> call to method WriteLine + +# 37| enter Switch +#-----| -> {...} + +# 37| exit Switch + +# 37| exit Switch (abnormal) +#-----| -> exit Switch + +# 37| exit Switch (normal) +#-----| -> exit Switch + +# 38| {...} +#-----| -> switch (...) {...} + +# 39| switch (...) {...} +#-----| -> access to parameter a + +# 39| access to parameter a +#-----| -> case ...: + +# 41| case ...: +#-----| -> 1 + +# 41| 1 +#-----| match -> ...; +#-----| no-match -> case ...: + +# 42| ...; +#-----| -> "1" + +# 42| call to method WriteLine +#-----| -> 2 + +# 42| "1" +#-----| -> call to method WriteLine + +# 43| goto case ...; +#-----| goto(2) -> case ...: + +# 43| 2 +#-----| -> goto case ...; + +# 44| case ...: +#-----| -> 2 + +# 44| 2 +#-----| match -> ...; +#-----| no-match -> case ...: + +# 45| ...; +#-----| -> "2" + +# 45| call to method WriteLine +#-----| -> 1 + +# 45| "2" +#-----| -> call to method WriteLine + +# 46| goto case ...; +#-----| goto(1) -> case ...: + +# 46| 1 +#-----| -> goto case ...; + +# 47| case ...: +#-----| -> 3 + +# 47| 3 +#-----| match -> ...; +#-----| no-match -> switch (...) {...} + +# 48| ...; +#-----| -> "3" + +# 48| call to method WriteLine +#-----| -> break; + +# 48| "3" +#-----| -> call to method WriteLine + +# 49| break; +#-----| break -> switch (...) {...} + +# 51| switch (...) {...} +#-----| -> access to parameter a + +# 51| access to parameter a +#-----| -> case ...: + +# 53| case ...: +#-----| -> 42 + +# 53| 42 +#-----| match -> ...; +#-----| no-match -> default: + +# 54| ...; +#-----| -> "The answer" + +# 54| call to method WriteLine +#-----| -> break; + +# 54| "The answer" +#-----| -> call to method WriteLine + +# 55| break; +#-----| break -> switch (...) {...} + +# 56| default: +#-----| -> ...; + +# 57| ...; +#-----| -> "Not the answer" + +# 57| call to method WriteLine +#-----| -> break; + +# 57| "Not the answer" +#-----| -> call to method WriteLine + +# 58| break; +#-----| break -> switch (...) {...} + +# 60| switch (...) {...} +#-----| -> this access + +# 60| call to method Parse +#-----| -> case ...: + +# 60| access to field Field +#-----| -> call to method Parse + +# 60| this access +#-----| -> access to field Field + +# 62| case ...: +#-----| -> 0 + +# 62| 0 +#-----| match -> if (...) ... +#-----| no-match -> access to parameter a + +# 63| if (...) ... +#-----| -> this access + +# 63| [false] !... +#-----| false -> break; + +# 63| [true] !... +#-----| true -> object creation of type NullReferenceException + +# 63| ... == ... +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 63| access to field Field +#-----| -> "" + +# 63| this access +#-----| -> access to field Field + +# 63| "" +#-----| -> ... == ... + +# 64| throw ...; +#-----| exception(NullReferenceException) -> exit Switch (abnormal) + +# 64| object creation of type NullReferenceException +#-----| -> throw ...; + +# 65| break; +#-----| break -> access to parameter a + +# 67| return ...; +#-----| return -> exit Switch (normal) + +# 67| access to parameter a +#-----| -> return ...; + +# 70| enter M +#-----| -> {...} + +# 70| exit M + +# 70| exit M (normal) +#-----| -> exit M + +# 71| {...} +#-----| -> if (...) ... + +# 72| if (...) ... +#-----| -> access to parameter s + +# 72| ... == ... +#-----| true -> return ...; +#-----| false -> if (...) ... + +# 72| access to parameter s +#-----| -> null + +# 72| null +#-----| -> ... == ... + +# 73| return ...; +#-----| return -> exit M (normal) + +# 74| if (...) ... +#-----| -> access to parameter s + +# 74| ... > ... +#-----| true -> {...} +#-----| false -> {...} + +# 74| access to property Length +#-----| -> 0 + +# 74| access to parameter s +#-----| -> access to property Length + +# 74| 0 +#-----| -> ... > ... + +# 75| {...} +#-----| -> ...; + +# 76| ...; +#-----| -> access to parameter s + +# 76| call to method WriteLine +#-----| -> exit M (normal) + +# 76| access to parameter s +#-----| -> call to method WriteLine + +# 79| {...} +#-----| -> ...; + +# 80| ...; +#-----| -> "" + +# 80| call to method WriteLine +#-----| -> exit M (normal) + +# 80| "" +#-----| -> call to method WriteLine + +# 84| enter M2 +#-----| -> {...} + +# 84| exit M2 + +# 84| exit M2 (normal) +#-----| -> exit M2 + +# 85| {...} +#-----| -> if (...) ... + +# 86| if (...) ... +#-----| -> access to parameter s + +# 86| [false] ... && ... +#-----| false -> exit M2 (normal) + +# 86| [true] ... && ... +#-----| true -> ...; + +# 86| ... != ... +#-----| false -> [false] ... && ... +#-----| true -> access to parameter s + +# 86| access to parameter s +#-----| -> null + +# 86| null +#-----| -> ... != ... + +# 86| ... > ... +#-----| false -> [false] ... && ... +#-----| true -> [true] ... && ... + +# 86| access to property Length +#-----| -> 0 + +# 86| access to parameter s +#-----| -> access to property Length + +# 86| 0 +#-----| -> ... > ... + +# 87| ...; +#-----| -> access to parameter s + +# 87| call to method WriteLine +#-----| -> exit M2 (normal) + +# 87| access to parameter s +#-----| -> call to method WriteLine + +# 90| enter M3 +#-----| -> {...} + +# 90| exit M3 + +# 90| exit M3 (abnormal) +#-----| -> exit M3 + +# 90| exit M3 (normal) +#-----| -> exit M3 + +# 91| {...} +#-----| -> if (...) ... + +# 92| if (...) ... +#-----| -> access to parameter s + +# 92| call to method Equals +#-----| true -> "s" +#-----| false -> ...; + +# 92| access to parameter s +#-----| -> null + +# 92| null +#-----| -> call to method Equals + +# 93| throw ...; +#-----| exception(ArgumentNullException) -> exit M3 (abnormal) + +# 93| object creation of type ArgumentNullException +#-----| -> throw ...; + +# 93| "s" +#-----| -> object creation of type ArgumentNullException + +# 94| ...; +#-----| -> access to parameter s + +# 94| call to method WriteLine +#-----| -> if (...) ... + +# 94| access to parameter s +#-----| -> call to method WriteLine + +# 96| if (...) ... +#-----| -> this access + +# 96| ... != ... +#-----| true -> ...; +#-----| false -> if (...) ... + +# 96| access to field Field +#-----| -> null + +# 96| this access +#-----| -> access to field Field + +# 96| null +#-----| -> ... != ... + +# 97| ...; +#-----| -> object creation of type ControlFlow + +# 97| call to method WriteLine +#-----| -> if (...) ... + +# 97| access to field Field +#-----| -> call to method WriteLine + +# 97| object creation of type ControlFlow +#-----| -> access to field Field + +# 99| if (...) ... +#-----| -> this access + +# 99| ... != ... +#-----| true -> ...; +#-----| false -> if (...) ... + +# 99| access to field Field +#-----| -> null + +# 99| this access +#-----| -> access to field Field + +# 99| null +#-----| -> ... != ... + +# 100| ...; +#-----| -> this access + +# 100| call to method WriteLine +#-----| -> if (...) ... + +# 100| access to field Field +#-----| -> call to method WriteLine + +# 100| this access +#-----| -> access to field Field + +# 102| if (...) ... +#-----| -> this access + +# 102| ... != ... +#-----| true -> ...; +#-----| false -> exit M3 (normal) + +# 102| access to property Prop +#-----| -> null + +# 102| this access +#-----| -> access to property Prop + +# 102| null +#-----| -> ... != ... + +# 103| ...; +#-----| -> this access + +# 103| call to method WriteLine +#-----| -> exit M3 (normal) + +# 103| access to property Prop +#-----| -> call to method WriteLine + +# 103| this access +#-----| -> access to property Prop + +# 106| enter M4 +#-----| -> {...} + +# 106| exit M4 + +# 106| exit M4 (normal) +#-----| -> exit M4 + +# 107| {...} +#-----| -> if (...) ... + +# 108| if (...) ... +#-----| -> access to parameter s + +# 108| ... != ... +#-----| true -> {...} +#-----| false -> ...; + +# 108| access to parameter s +#-----| -> null + +# 108| null +#-----| -> ... != ... + +# 109| {...} +#-----| -> while (...) ... + +# 110| while (...) ... +#-----| -> true + +# 110| true +#-----| true -> {...} + +# 111| {...} +#-----| -> ...; + +# 112| ...; +#-----| -> access to parameter s + +# 112| call to method WriteLine +#-----| -> true + +# 112| access to parameter s +#-----| -> call to method WriteLine + +# 116| ...; +#-----| -> access to parameter s + +# 116| call to method WriteLine +#-----| -> exit M4 (normal) + +# 116| access to parameter s +#-----| -> call to method WriteLine + +# 119| enter M5 +#-----| -> {...} + +# 119| exit M5 + +# 119| exit M5 (normal) +#-----| -> exit M5 + +# 120| {...} +#-----| -> ... ...; + +# 121| ... ...; +#-----| -> access to parameter s + +# 121| String x = ... +#-----| -> ...; + +# 121| access to parameter s +#-----| -> String x = ... + +# 122| ...; +#-----| -> access to local variable x + +# 122| ... = ... +#-----| -> access to local variable x + +# 122| ... + ... +#-----| -> ... = ... + +# 122| access to local variable x +#-----| -> " " + +# 122| " " +#-----| -> ... + ... + +# 123| return ...; +#-----| return -> exit M5 (normal) + +# 123| access to local variable x +#-----| -> return ...; + +# 127| enter get_Prop +#-----| -> {...} + +# 127| exit get_Prop + +# 127| exit get_Prop (normal) +#-----| -> exit get_Prop + +# 127| {...} +#-----| -> this access + +# 127| return ...; +#-----| return -> exit get_Prop (normal) + +# 127| ... ? ... : ... +#-----| -> return ...; + +# 127| ... == ... +#-----| true -> "" +#-----| false -> this access + +# 127| access to field Field +#-----| -> null + +# 127| this access +#-----| -> access to field Field + +# 127| null +#-----| -> ... == ... + +# 127| "" +#-----| -> ... ? ... : ... + +# 127| access to field Field +#-----| -> ... ? ... : ... + +# 127| this access +#-----| -> access to field Field + +# 127| enter set_Prop +#-----| -> {...} + +# 127| exit set_Prop + +# 127| exit set_Prop (normal) +#-----| -> exit set_Prop + +# 127| {...} +#-----| -> ...; + +# 127| ...; +#-----| -> this access + +# 127| ... = ... +#-----| -> exit set_Prop (normal) + +# 127| this access +#-----| -> access to parameter value + +# 127| access to parameter value +#-----| -> ... = ... + +# 129| enter ControlFlow +#-----| -> call to constructor Object + +# 129| call to constructor Object +#-----| -> {...} + +# 129| exit ControlFlow + +# 129| exit ControlFlow (normal) +#-----| -> exit ControlFlow + +# 130| {...} +#-----| -> ...; + +# 131| ...; +#-----| -> this access + +# 131| ... = ... +#-----| -> exit ControlFlow (normal) + +# 131| this access +#-----| -> access to parameter s + +# 131| access to parameter s +#-----| -> ... = ... + +# 134| enter ControlFlow +#-----| -> access to parameter i + +# 134| exit ControlFlow + +# 134| exit ControlFlow (normal) +#-----| -> exit ControlFlow + +# 134| call to constructor ControlFlow +#-----| -> {...} + +# 134| ... + ... +#-----| -> call to constructor ControlFlow + +# 134| (...) ... +#-----| -> "" + +# 134| access to parameter i +#-----| -> (...) ... + +# 134| "" +#-----| -> ... + ... + +# 134| {...} +#-----| -> exit ControlFlow (normal) + +# 136| enter ControlFlow +#-----| -> 0 + +# 136| exit ControlFlow + +# 136| exit ControlFlow (normal) +#-----| -> exit ControlFlow + +# 136| call to constructor ControlFlow +#-----| -> {...} + +# 136| ... + ... +#-----| -> call to constructor ControlFlow + +# 136| 0 +#-----| -> 1 + +# 136| 1 +#-----| -> ... + ... + +# 136| {...} +#-----| -> exit ControlFlow (normal) + +# 138| enter + +#-----| -> {...} + +# 138| exit + + +# 138| exit + (normal) +#-----| -> exit + + +# 139| {...} +#-----| -> ...; + +# 140| ...; +#-----| -> access to parameter x + +# 140| call to method WriteLine +#-----| -> access to parameter y + +# 140| access to parameter x +#-----| -> call to method WriteLine + +# 141| return ...; +#-----| return -> exit + (normal) + +# 141| access to parameter y +#-----| -> return ...; + +# 144| enter get_Item +#-----| -> {...} + +# 144| exit get_Item + +# 144| exit get_Item (normal) +#-----| -> exit get_Item + +# 144| {...} +#-----| -> access to parameter i + +# 144| return ...; +#-----| return -> exit get_Item (normal) + +# 144| ... + ... +#-----| -> return ...; + +# 144| (...) ... +#-----| -> "" + +# 144| access to parameter i +#-----| -> (...) ... + +# 144| "" +#-----| -> ... + ... + +# 144| enter set_Item +#-----| -> {...} + +# 144| exit set_Item + +# 144| exit set_Item (normal) +#-----| -> exit set_Item + +# 144| {...} +#-----| -> exit set_Item (normal) + +# 146| enter For +#-----| -> {...} + +# 146| exit For + +# 146| exit For (normal) +#-----| -> exit For + +# 147| {...} +#-----| -> ... ...; + +# 148| ... ...; +#-----| -> 0 + +# 148| Int32 x = ... +#-----| -> for (...;...;...) ... + +# 148| 0 +#-----| -> Int32 x = ... + +# 149| for (...;...;...) ... +#-----| -> access to local variable x + +# 149| ... < ... +#-----| true -> ...; +#-----| false -> for (...;...;...) ... + +# 149| access to local variable x +#-----| -> 10 + +# 149| 10 +#-----| -> ... < ... + +# 149| ++... +#-----| -> access to local variable x + +# 149| access to local variable x +#-----| -> ++... + +# 150| ...; +#-----| -> access to local variable x + +# 150| call to method WriteLine +#-----| -> access to local variable x + +# 150| access to local variable x +#-----| -> call to method WriteLine + +# 152| for (...;...;...) ... +#-----| -> {...} + +# 152| ...++ +#-----| -> {...} + +# 152| access to local variable x +#-----| -> ...++ + +# 153| {...} +#-----| -> ...; + +# 154| ...; +#-----| -> access to local variable x + +# 154| call to method WriteLine +#-----| -> if (...) ... + +# 154| access to local variable x +#-----| -> call to method WriteLine + +# 155| if (...) ... +#-----| -> access to local variable x + +# 155| ... > ... +#-----| false -> access to local variable x +#-----| true -> break; + +# 155| access to local variable x +#-----| -> 20 + +# 155| 20 +#-----| -> ... > ... + +# 156| break; +#-----| break -> for (...;...;...) ... + +# 159| for (...;...;...) ... +#-----| -> {...} + +# 160| {...} +#-----| -> ...; + +# 161| ...; +#-----| -> access to local variable x + +# 161| call to method WriteLine +#-----| -> ...; + +# 161| access to local variable x +#-----| -> call to method WriteLine + +# 162| ...; +#-----| -> access to local variable x + +# 162| ...++ +#-----| -> if (...) ... + +# 162| access to local variable x +#-----| -> ...++ + +# 163| if (...) ... +#-----| -> access to local variable x + +# 163| ... > ... +#-----| false -> {...} +#-----| true -> break; + +# 163| access to local variable x +#-----| -> 30 + +# 163| 30 +#-----| -> ... > ... + +# 164| break; +#-----| break -> for (...;...;...) ... + +# 167| for (...;...;...) ... +#-----| -> access to local variable x + +# 167| ... < ... +#-----| true -> {...} +#-----| false -> for (...;...;...) ... + +# 167| access to local variable x +#-----| -> 40 + +# 167| 40 +#-----| -> ... < ... + +# 168| {...} +#-----| -> ...; + +# 169| ...; +#-----| -> access to local variable x + +# 169| call to method WriteLine +#-----| -> ...; + +# 169| access to local variable x +#-----| -> call to method WriteLine + +# 170| ...; +#-----| -> access to local variable x + +# 170| ...++ +#-----| -> access to local variable x + +# 170| access to local variable x +#-----| -> ...++ + +# 173| for (...;...;...) ... +#-----| -> 0 + +# 173| Int32 i = ... +#-----| -> 0 + +# 173| 0 +#-----| -> Int32 i = ... + +# 173| Int32 j = ... +#-----| -> access to local variable i + +# 173| 0 +#-----| -> Int32 j = ... + +# 173| ... < ... +#-----| true -> {...} +#-----| false -> exit For (normal) + +# 173| ... + ... +#-----| -> 10 + +# 173| access to local variable i +#-----| -> access to local variable j + +# 173| access to local variable j +#-----| -> ... + ... + +# 173| 10 +#-----| -> ... < ... + +# 173| ...++ +#-----| -> access to local variable j + +# 173| access to local variable i +#-----| -> ...++ + +# 173| ...++ +#-----| -> access to local variable i + +# 173| access to local variable j +#-----| -> ...++ + +# 174| {...} +#-----| -> ...; + +# 175| ...; +#-----| -> access to local variable i + +# 175| call to method WriteLine +#-----| -> access to local variable i + +# 175| ... + ... +#-----| -> call to method WriteLine + +# 175| access to local variable i +#-----| -> access to local variable j + +# 175| access to local variable j +#-----| -> ... + ... + +# 179| enter Lambdas +#-----| -> {...} + +# 179| exit Lambdas + +# 179| exit Lambdas (normal) +#-----| -> exit Lambdas + +# 180| {...} +#-----| -> ... ...; + +# 181| ... ...; +#-----| -> (...) => ... + +# 181| Func y = ... +#-----| -> ... ...; + +# 181| enter (...) => ... +#-----| -> access to parameter x + +# 181| (...) => ... +#-----| -> Func y = ... + +# 181| exit (...) => ... + +# 181| exit (...) => ... (normal) +#-----| -> exit (...) => ... + +# 181| ... + ... +#-----| -> exit (...) => ... (normal) + +# 181| access to parameter x +#-----| -> 1 + +# 181| 1 +#-----| -> ... + ... + +# 182| ... ...; +#-----| -> delegate(...) { ... } + +# 182| Func z = ... +#-----| -> exit Lambdas (normal) + +# 182| enter delegate(...) { ... } +#-----| -> {...} + +# 182| delegate(...) { ... } +#-----| -> Func z = ... + +# 182| exit delegate(...) { ... } + +# 182| exit delegate(...) { ... } (normal) +#-----| -> exit delegate(...) { ... } + +# 182| {...} +#-----| -> access to parameter x + +# 182| return ...; +#-----| return -> exit delegate(...) { ... } (normal) + +# 182| ... + ... +#-----| -> return ...; + +# 182| access to parameter x +#-----| -> 1 + +# 182| 1 +#-----| -> ... + ... + +# 185| enter LogicalOr +#-----| -> {...} + +# 185| exit LogicalOr + +# 185| exit LogicalOr (normal) +#-----| -> exit LogicalOr + +# 186| {...} +#-----| -> if (...) ... + +# 187| if (...) ... +#-----| -> 1 + +# 187| [false] ... || ... +#-----| false -> ...; + +# 187| [false] ... || ... +#-----| false -> 1 + +# 187| ... == ... +#-----| false -> 2 + +# 187| 1 +#-----| -> 2 + +# 187| 2 +#-----| -> ... == ... + +# 187| ... == ... +#-----| false -> [false] ... || ... + +# 187| 2 +#-----| -> 3 + +# 187| 3 +#-----| -> ... == ... + +# 187| [false] ... && ... +#-----| false -> [false] ... || ... + +# 187| ... == ... +#-----| false -> [false] ... && ... + +# 187| 1 +#-----| -> 3 + +# 187| 3 +#-----| -> ... == ... + +# 190| ...; +#-----| -> "This should happen" + +# 190| call to method WriteLine +#-----| -> exit LogicalOr (normal) + +# 190| "This should happen" +#-----| -> call to method WriteLine + +# 193| enter Booleans +#-----| -> {...} + +# 193| exit Booleans + +# 193| exit Booleans (abnormal) +#-----| -> exit Booleans + +# 193| exit Booleans (normal) +#-----| -> exit Booleans + +# 194| {...} +#-----| -> ... ...; + +# 195| ... ...; +#-----| -> this access + +# 195| Boolean b = ... +#-----| -> if (...) ... + +# 195| ... && ... +#-----| -> Boolean b = ... + +# 195| ... > ... +#-----| false -> ... && ... +#-----| true -> this access + +# 195| access to property Length +#-----| -> 0 + +# 195| access to field Field +#-----| -> access to property Length + +# 195| this access +#-----| -> access to field Field + +# 195| 0 +#-----| -> ... > ... + +# 195| !... +#-----| -> ... && ... + +# 195| ... == ... +#-----| -> !... + +# 195| access to property Length +#-----| -> 1 + +# 195| access to field Field +#-----| -> access to property Length + +# 195| this access +#-----| -> access to field Field + +# 195| 1 +#-----| -> ... == ... + +# 197| if (...) ... +#-----| -> this access + +# 197| [false] !... +#-----| false -> if (...) ... + +# 197| [true] !... +#-----| true -> ...; + +# 197| [false] ... ? ... : ... +#-----| false -> [true] !... + +# 197| [true] ... ? ... : ... +#-----| true -> [false] !... + +# 197| ... == ... +#-----| true -> false +#-----| false -> true + +# 197| access to property Length +#-----| -> 0 + +# 197| access to field Field +#-----| -> access to property Length + +# 197| this access +#-----| -> access to field Field + +# 197| 0 +#-----| -> ... == ... + +# 197| false +#-----| false -> [false] ... ? ... : ... + +# 197| true +#-----| true -> [true] ... ? ... : ... + +# 198| ...; +#-----| -> this access + +# 198| ... = ... +#-----| -> if (...) ... + +# 198| ... ? ... : ... +#-----| -> ... = ... + +# 198| ... == ... +#-----| true -> false +#-----| false -> true + +# 198| access to property Length +#-----| -> 0 + +# 198| access to field Field +#-----| -> access to property Length + +# 198| this access +#-----| -> access to field Field + +# 198| 0 +#-----| -> ... == ... + +# 198| false +#-----| -> ... ? ... : ... + +# 198| true +#-----| -> ... ? ... : ... + +# 200| if (...) ... +#-----| -> this access + +# 200| [false] ... || ... +#-----| false -> exit Booleans (normal) + +# 200| [true] ... || ... +#-----| true -> {...} + +# 200| [false] !... +#-----| false -> this access + +# 200| [true] !... +#-----| true -> [true] ... || ... + +# 200| ... == ... +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 200| access to property Length +#-----| -> 0 + +# 200| access to field Field +#-----| -> access to property Length + +# 200| this access +#-----| -> access to field Field + +# 200| 0 +#-----| -> ... == ... + +# 200| [false] !... +#-----| false -> [false] ... || ... + +# 200| [true] !... +#-----| true -> [true] ... || ... + +# 200| [false] !... +#-----| false -> [true] !... + +# 200| [true] !... +#-----| true -> [false] !... + +# 200| [false] ... && ... +#-----| false -> [true] !... + +# 200| [true] ... && ... +#-----| true -> [false] !... + +# 200| ... == ... +#-----| false -> [false] ... && ... +#-----| true -> access to local variable b + +# 200| access to property Length +#-----| -> 1 + +# 200| access to field Field +#-----| -> access to property Length + +# 200| this access +#-----| -> access to field Field + +# 200| 1 +#-----| -> ... == ... + +# 200| access to local variable b +#-----| false -> [false] ... && ... +#-----| true -> [true] ... && ... + +# 201| {...} +#-----| -> {...} + +# 202| {...} +#-----| -> object creation of type Exception + +# 203| throw ...; +#-----| exception(Exception) -> exit Booleans (abnormal) + +# 203| object creation of type Exception +#-----| -> throw ...; + +# 208| enter Do +#-----| -> {...} + +# 208| exit Do + +# 208| exit Do (normal) +#-----| -> exit Do + +# 209| {...} +#-----| -> do ... while (...); + +# 210| do ... while (...); +#-----| -> {...} + +# 211| {...} +#-----| -> ...; + +# 212| ...; +#-----| -> this access + +# 212| ... = ... +#-----| -> if (...) ... + +# 212| this access +#-----| -> this access + +# 212| ... + ... +#-----| -> ... = ... + +# 212| access to field Field +#-----| -> "a" + +# 212| this access +#-----| -> access to field Field + +# 212| "a" +#-----| -> ... + ... + +# 213| if (...) ... +#-----| -> this access + +# 213| ... > ... +#-----| true -> {...} +#-----| false -> if (...) ... + +# 213| access to property Length +#-----| -> 0 + +# 213| access to field Field +#-----| -> access to property Length + +# 213| this access +#-----| -> access to field Field + +# 213| 0 +#-----| -> ... > ... + +# 214| {...} +#-----| -> continue; + +# 215| continue; +#-----| continue -> this access + +# 217| if (...) ... +#-----| -> this access + +# 217| ... < ... +#-----| true -> {...} +#-----| false -> this access + +# 217| access to property Length +#-----| -> 0 + +# 217| access to field Field +#-----| -> access to property Length + +# 217| this access +#-----| -> access to field Field + +# 217| 0 +#-----| -> ... < ... + +# 218| {...} +#-----| -> break; + +# 219| break; +#-----| break -> exit Do (normal) + +# 221| ... < ... +#-----| true -> {...} +#-----| false -> exit Do (normal) + +# 221| access to property Length +#-----| -> 10 + +# 221| access to field Field +#-----| -> access to property Length + +# 221| this access +#-----| -> access to field Field + +# 221| 10 +#-----| -> ... < ... + +# 224| enter Foreach +#-----| -> {...} + +# 224| exit Foreach + +# 224| exit Foreach (normal) +#-----| -> exit Foreach + +# 225| {...} +#-----| -> "a" + +# 226| foreach (... ... in ...) ... +#-----| non-empty -> String x +#-----| empty -> exit Foreach (normal) + +# 226| String x +#-----| -> {...} + +# 226| call to method Repeat +#-----| -> foreach (... ... in ...) ... + +# 226| "a" +#-----| -> 10 + +# 226| 10 +#-----| -> call to method Repeat + +# 227| {...} +#-----| -> ...; + +# 228| ...; +#-----| -> this access + +# 228| ... = ... +#-----| -> if (...) ... + +# 228| this access +#-----| -> this access + +# 228| ... + ... +#-----| -> ... = ... + +# 228| access to field Field +#-----| -> access to local variable x + +# 228| this access +#-----| -> access to field Field + +# 228| access to local variable x +#-----| -> ... + ... + +# 229| if (...) ... +#-----| -> this access + +# 229| ... > ... +#-----| true -> {...} +#-----| false -> if (...) ... + +# 229| access to property Length +#-----| -> 0 + +# 229| access to field Field +#-----| -> access to property Length + +# 229| this access +#-----| -> access to field Field + +# 229| 0 +#-----| -> ... > ... + +# 230| {...} +#-----| -> continue; + +# 231| continue; +#-----| continue -> foreach (... ... in ...) ... + +# 233| if (...) ... +#-----| -> this access + +# 233| ... < ... +#-----| false -> foreach (... ... in ...) ... +#-----| true -> {...} + +# 233| access to property Length +#-----| -> 0 + +# 233| access to field Field +#-----| -> access to property Length + +# 233| this access +#-----| -> access to field Field + +# 233| 0 +#-----| -> ... < ... + +# 234| {...} +#-----| -> break; + +# 235| break; +#-----| break -> exit Foreach (normal) + +# 240| enter Goto +#-----| -> {...} + +# 240| exit Goto + +# 240| exit Goto (normal) +#-----| -> exit Goto + +# 241| {...} +#-----| -> Label: + +# 242| Label: +#-----| -> if (...) ... + +# 242| if (...) ... +#-----| -> this access + +# 242| [false] !... +#-----| false -> if (...) ... + +# 242| [true] !... +#-----| true -> {...} + +# 242| [false] !... +#-----| false -> [true] !... + +# 242| [true] !... +#-----| true -> [false] !... + +# 242| ... == ... +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 242| access to property Length +#-----| -> 0 + +# 242| access to field Field +#-----| -> access to property Length + +# 242| this access +#-----| -> access to field Field + +# 242| 0 +#-----| -> ... == ... + +# 242| {...} +#-----| -> if (...) ... + +# 244| if (...) ... +#-----| -> this access + +# 244| ... > ... +#-----| true -> goto ...; +#-----| false -> switch (...) {...} + +# 244| access to property Length +#-----| -> 0 + +# 244| access to field Field +#-----| -> access to property Length + +# 244| this access +#-----| -> access to field Field + +# 244| 0 +#-----| -> ... > ... + +# 244| goto ...; +#-----| goto(Label) -> Label: + +# 246| switch (...) {...} +#-----| -> this access + +# 246| ... + ... +#-----| -> case ...: + +# 246| access to property Length +#-----| -> 3 + +# 246| access to field Field +#-----| -> access to property Length + +# 246| this access +#-----| -> access to field Field + +# 246| 3 +#-----| -> ... + ... + +# 248| case ...: +#-----| -> 0 + +# 248| 0 +#-----| match -> goto default; +#-----| no-match -> case ...: + +# 249| goto default; +#-----| goto(default) -> default: + +# 250| case ...: +#-----| -> 1 + +# 250| 1 +#-----| match -> ...; +#-----| no-match -> case ...: + +# 251| ...; +#-----| -> 1 + +# 251| call to method WriteLine +#-----| -> break; + +# 251| 1 +#-----| -> call to method WriteLine + +# 252| break; +#-----| break -> exit Goto (normal) + +# 253| case ...: +#-----| -> 2 + +# 253| 2 +#-----| match -> goto ...; +#-----| no-match -> default: + +# 254| goto ...; +#-----| goto(Label) -> Label: + +# 255| default: +#-----| -> ...; + +# 256| ...; +#-----| -> 0 + +# 256| call to method WriteLine +#-----| -> break; + +# 256| 0 +#-----| -> call to method WriteLine + +# 257| break; +#-----| break -> exit Goto (normal) + +# 261| enter Yield +#-----| -> {...} + +# 261| exit Yield + +# 261| exit Yield (normal) +#-----| -> exit Yield + +# 262| {...} +#-----| -> 0 + +# 263| yield return ...; +#-----| -> for (...;...;...) ... + +# 263| 0 +#-----| -> yield return ...; + +# 264| for (...;...;...) ... +#-----| -> 1 + +# 264| Int32 i = ... +#-----| -> access to local variable i + +# 264| 1 +#-----| -> Int32 i = ... + +# 264| ... < ... +#-----| true -> {...} +#-----| false -> try {...} ... + +# 264| access to local variable i +#-----| -> 10 + +# 264| 10 +#-----| -> ... < ... + +# 264| ...++ +#-----| -> access to local variable i + +# 264| access to local variable i +#-----| -> ...++ + +# 265| {...} +#-----| -> access to local variable i + +# 266| yield return ...; +#-----| -> access to local variable i + +# 266| access to local variable i +#-----| -> yield return ...; + +# 268| try {...} ... +#-----| -> {...} + +# 269| {...} +#-----| -> yield break; + +# 270| yield break; +#-----| return -> [finally: return] {...} + +# 274| [finally: return] {...} +#-----| -> [finally: return] ...; + +# 275| [finally: return] ...; +#-----| -> [finally: return] "not dead" + +# 275| [finally: return] call to method WriteLine +#-----| return -> exit Yield (normal) + +# 275| [finally: return] "not dead" +#-----| -> [finally: return] call to method WriteLine + +# 282| enter ControlFlowSub +#-----| -> call to constructor ControlFlow + +# 282| exit ControlFlowSub + +# 282| exit ControlFlowSub (normal) +#-----| -> exit ControlFlowSub + +# 282| call to constructor ControlFlow +#-----| -> {...} + +# 282| {...} +#-----| -> exit ControlFlowSub (normal) + +# 284| enter ControlFlowSub +#-----| -> call to constructor ControlFlowSub + +# 284| exit ControlFlowSub + +# 284| exit ControlFlowSub (normal) +#-----| -> exit ControlFlowSub + +# 284| call to constructor ControlFlowSub +#-----| -> {...} + +# 284| {...} +#-----| -> exit ControlFlowSub (normal) + +# 286| enter ControlFlowSub +#-----| -> access to parameter i + +# 286| exit ControlFlowSub + +# 286| exit ControlFlowSub (normal) +#-----| -> exit ControlFlowSub + +# 286| call to constructor ControlFlowSub +#-----| -> {...} + +# 286| call to method ToString +#-----| -> call to constructor ControlFlowSub + +# 286| access to parameter i +#-----| -> call to method ToString + +# 286| {...} +#-----| -> exit ControlFlowSub (normal) + +# 291| enter M +#-----| -> access to parameter f + +# 291| exit M + +# 291| exit M (normal) +#-----| -> exit M + +# 291| delegate call +#-----| -> exit M (normal) + +# 291| access to parameter f +#-----| -> 0 + +# 291| 0 +#-----| -> delegate call + +# 296| enter NegationInConstructor +#-----| -> call to constructor Object + +# 296| call to constructor Object +#-----| -> {...} + +# 296| exit NegationInConstructor + +# 296| exit NegationInConstructor (normal) +#-----| -> exit NegationInConstructor + +# 296| {...} +#-----| -> exit NegationInConstructor (normal) + +# 298| enter M +#-----| -> {...} + +# 298| exit M + +# 298| exit M (normal) +#-----| -> exit M + +# 299| {...} +#-----| -> ...; + +# 300| ...; +#-----| -> 0 + +# 300| object creation of type NegationInConstructor +#-----| -> exit M (normal) + +# 300| 0 +#-----| -> access to parameter i + +# 300| ... && ... +#-----| -> "" + +# 300| [false] !... +#-----| false -> ... && ... + +# 300| [true] !... +#-----| true -> access to parameter s + +# 300| ... > ... +#-----| true -> [false] !... +#-----| false -> [true] !... + +# 300| access to parameter i +#-----| -> 0 + +# 300| 0 +#-----| -> ... > ... + +# 300| ... != ... +#-----| -> ... && ... + +# 300| access to parameter s +#-----| -> null + +# 300| null +#-----| -> ... != ... + +# 300| "" +#-----| -> object creation of type NegationInConstructor diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.ql b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.ql index 4a1cf5b5880..cf1ba3f9598 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.ql +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.ql @@ -1,11 +1,9 @@ +/** + * @kind graph + */ + import csharp import Common +import semmle.code.csharp.controlflow.internal.ControlFlowGraphImplShared::TestOutput -query predicate edges( - SourceControlFlowNode node, SourceControlFlowNode successor, string attr, string val -) { - exists(ControlFlow::SuccessorType t | successor = node.getASuccessorByType(t) | - attr = "semmle.label" and - val = t.toString() - ) -} +private class MyRelevantNode extends RelevantNode, SourceControlFlowNode { } From c80a1da48366d54471da7a7d1a7fcfbe327c478e Mon Sep 17 00:00:00 2001 From: Fosstars Date: Wed, 25 Aug 2021 12:11:34 +0200 Subject: [PATCH 346/429] Don't consider copyOf() and clone() in ArrayUpdate --- .../java/security/StaticInitializationVectorQuery.qll | 10 ---------- .../security/CWE-1204/StaticInitializationVector.java | 3 ++- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index c5f43de99b6..cbddf2b6450 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -50,12 +50,6 @@ private class ArrayUpdate extends Expr { ma.getArgument(2) = array ) or - exists(StaticMethodAccess ma | - ma.getMethod().hasQualifiedName("java.util", "Arrays", ["copyOf", "copyOfRange"]) and - ma = this and - ma = array - ) - or exists(MethodAccess ma, Method m | m = ma.getMethod() and ma = this and @@ -66,10 +60,6 @@ private class ArrayUpdate extends Expr { m.hasQualifiedName("java.security", "SecureRandom", "nextBytes") or m.hasQualifiedName("java.util", "Random", "nextBytes") ) - or - exists(MethodAccess ma, Method m | m = ma.getMethod() | - m.getDeclaringType().hasName("byte[]") and m.hasName("clone") and ma = this and ma = array - ) } /** Returns the updated array. */ diff --git a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java index 05ae7e4dd8b..f964d17239b 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java +++ b/java/ql/test/experimental/query-tests/security/CWE-1204/StaticInitializationVector.java @@ -153,7 +153,8 @@ public class StaticInitializationVector { byte[] randomBytes = new byte[16]; SecureRandom.getInstanceStrong().nextBytes(randomBytes); - byte[] iv = Arrays.copyOf(randomBytes, 16); + byte[] iv = new byte[16]; + iv = Arrays.copyOf(randomBytes, 16); GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); From 86b7b2b86dccd4517e32b94e19c44c361073c513 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Wed, 25 Aug 2021 12:14:36 +0200 Subject: [PATCH 347/429] Updated qldoc for ArrayUpdate --- .../code/java/security/StaticInitializationVectorQuery.qll | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index cbddf2b6450..5e192ee326e 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -28,12 +28,7 @@ private class StaticByteArrayCreation extends ArrayCreationExpr { } } -/** - * Defines a sub-set of expressions that update either content of an array or an array reference. - * This sub-set covers only methods that are likely to set a non-static IV. - * For example, `java.util.Arrays.fill()` is not covered because it assigns the same value - * to each element of the array. - */ +/** Defines a sub-set of expressions that update an array. */ private class ArrayUpdate extends Expr { Expr array; From f97c8bb049fb4607da97bf632997dbfef9b08269 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Wed, 25 Aug 2021 12:40:48 +0200 Subject: [PATCH 348/429] Removed sanitizer in StaticInitializationVectorConfig --- .../code/java/security/StaticInitializationVectorQuery.qll | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index 5e192ee326e..c41cc045f5f 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -161,8 +161,4 @@ class StaticInitializationVectorConfig extends TaintTracking::Configuration { override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { createInitializationVectorSpecStep(fromNode, toNode) } - - override predicate isSanitizer(DataFlow::Node node) { - exists(ArrayUpdate update | update.getArray() = node.asExpr()) - } } From cd40de7464adfa9d869f28ad1068fb25d6414ef9 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 25 Aug 2021 09:40:55 -0500 Subject: [PATCH 349/429] Update javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql Typo fix Co-authored-by: Asger F --- javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql b/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql index 349e00338c4..e8cd8ac81e4 100644 --- a/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql +++ b/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql @@ -25,7 +25,7 @@ SourceNode clipboardDataTransferSource(TypeTracker t) { t.start() and exists(DataFlow::PropRead pr | pr.getPropertyName() = "clipboardData" and pr.flowsTo(result)) or - exists(TypeTracker t2 | result = clipboardDataSource(t2).track(t2, t)) + exists(TypeTracker t2 | result = clipboardDataTransferSource(t2).track(t2, t)) } SourceNode clipboardDataTransferSource() { From f41828e5dbf8ae99fd33bc20ceee94e23ee321fb Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Wed, 25 Aug 2021 19:38:33 +0200 Subject: [PATCH 350/429] Better qldoc in StaticInitializationVectorQuery.qll Co-authored-by: Chris Smowton --- .../code/java/security/StaticInitializationVectorQuery.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index c41cc045f5f..b442277cf6e 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -10,6 +10,9 @@ private predicate initializedWithConstants(ArrayCreationExpr array) { not exists(array.getInit()) or // creating a multidimensional array with an initializer like `{ new byte[8], new byte[16] }` + // This works around https://github.com/github/codeql/issues/6552 -- change me once there is + // a better way to distinguish nested initializers that create zero-filled arrays + // (e.g. `new byte[1]`) from those with an initializer list (`new byte[] { 1 }` or just `{ 1 }`) array.getInit().getAnInit().getAChildExpr() instanceof IntegerLiteral or // creating an array wit an initializer like `new byte[] { 1, 2 }` @@ -28,7 +31,7 @@ private class StaticByteArrayCreation extends ArrayCreationExpr { } } -/** Defines a sub-set of expressions that update an array. */ +/** An expression that updates `array`. */ private class ArrayUpdate extends Expr { Expr array; From 23e23226358bf5276ee6d9f8d6e6f0e570155bea Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Wed, 25 Aug 2021 19:43:43 +0200 Subject: [PATCH 351/429] Simplify ArrayUpdate Co-authored-by: Chris Smowton --- .../code/java/security/StaticInitializationVectorQuery.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index b442277cf6e..119e457bb3f 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -36,9 +36,9 @@ private class ArrayUpdate extends Expr { Expr array; ArrayUpdate() { - exists(Assignment assign, ArrayAccess arrayAccess | arrayAccess = assign.getDest() | + exists(Assignment assign | assign = this and - arrayAccess.getArray() = array and + assign.getDest().(ArrayAccess).getArray() = array and not assign.getSource() instanceof CompileTimeConstantExpr ) or From 45d1fa7f01af4187afe32969d5bdf443753f9961 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Wed, 25 Aug 2021 12:02:31 -0700 Subject: [PATCH 352/429] Packaging: Rafactor Javascript core libraries Extract the external facing `qll` files into the codeql/javascript-all query pack. --- javascript/ql/examples/qlpack.lock.yml | 4 ++++ javascript/ql/examples/qlpack.yml | 2 +- javascript/ql/{src => lib}/Customizations.qll | 0 javascript/ql/{src => lib}/default.qll | 0 javascript/ql/{src => lib}/javascript.qll | 0 javascript/ql/lib/qlpack.lock.yml | 4 ++++ javascript/ql/lib/qlpack.yml | 7 +++++++ javascript/ql/{src => lib}/semmle/files/FileSystem.qll | 0 javascript/ql/{src => lib}/semmle/javascript/AMD.qll | 0 javascript/ql/{src => lib}/semmle/javascript/AST.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Aliases.qll | 0 .../ql/{src => lib}/semmle/javascript/ApiGraphs.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Arrays.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Base64.qll | 0 .../ql/{src => lib}/semmle/javascript/BasicBlocks.qll | 0 javascript/ql/{src => lib}/semmle/javascript/CFG.qll | 0 .../ql/{src => lib}/semmle/javascript/CanonicalNames.qll | 0 .../{src => lib}/semmle/javascript/CharacterEscapes.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Classes.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Closure.qll | 0 .../ql/{src => lib}/semmle/javascript/Collections.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Comments.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Concepts.qll | 0 .../ql/{src => lib}/semmle/javascript/Constants.qll | 0 javascript/ql/{src => lib}/semmle/javascript/DOM.qll | 0 javascript/ql/{src => lib}/semmle/javascript/DefUse.qll | 0 .../semmle/javascript/DefensiveProgramming.qll | 0 .../semmle/javascript/DynamicPropertyAccess.qll | 0 javascript/ql/{src => lib}/semmle/javascript/E4X.qll | 0 .../ql/{src => lib}/semmle/javascript/ES2015Modules.qll | 0 .../ql/{src => lib}/semmle/javascript/EmailClients.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Errors.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Expr.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Extend.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Externs.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Files.qll | 0 .../ql/{src => lib}/semmle/javascript/Functions.qll | 0 .../ql/{src => lib}/semmle/javascript/GeneratedCode.qll | 0 .../ql/{src => lib}/semmle/javascript/Generators.qll | 0 .../{src => lib}/semmle/javascript/GlobalAccessPaths.qll | 0 javascript/ql/{src => lib}/semmle/javascript/HTML.qll | 0 .../ql/{src => lib}/semmle/javascript/HtmlSanitizers.qll | 0 .../ql/{src => lib}/semmle/javascript/InclusionTests.qll | 0 javascript/ql/{src => lib}/semmle/javascript/JSDoc.qll | 0 javascript/ql/{src => lib}/semmle/javascript/JSON.qll | 0 javascript/ql/{src => lib}/semmle/javascript/JSX.qll | 0 .../ql/{src => lib}/semmle/javascript/JsonParsers.qll | 0 .../ql/{src => lib}/semmle/javascript/JsonSchema.qll | 0 .../{src => lib}/semmle/javascript/JsonStringifiers.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Lines.qll | 0 .../ql/{src => lib}/semmle/javascript/Locations.qll | 0 .../semmle/javascript/MembershipCandidates.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Modules.qll | 0 javascript/ql/{src => lib}/semmle/javascript/NPM.qll | 0 javascript/ql/{src => lib}/semmle/javascript/NodeJS.qll | 0 .../semmle/javascript/NodeModuleResolutionImpl.qll | 0 .../ql/{src => lib}/semmle/javascript/PackageExports.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Paths.qll | 0 javascript/ql/{src => lib}/semmle/javascript/PrintAst.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Promises.qll | 0 .../ql/{src => lib}/semmle/javascript/RangeAnalysis.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Regexp.qll | 0 .../semmle/javascript/RestrictedLocations.qll | 0 javascript/ql/{src => lib}/semmle/javascript/SSA.qll | 0 .../ql/{src => lib}/semmle/javascript/SourceMaps.qll | 0 .../ql/{src => lib}/semmle/javascript/StandardLibrary.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Stmt.qll | 0 .../semmle/javascript/StringConcatenation.qll | 0 .../ql/{src => lib}/semmle/javascript/StringOps.qll | 0 .../ql/{src => lib}/semmle/javascript/Templates.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Tokens.qll | 0 .../ql/{src => lib}/semmle/javascript/TypeAnnotations.qll | 0 .../ql/{src => lib}/semmle/javascript/TypeScript.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Unit.qll | 0 javascript/ql/{src => lib}/semmle/javascript/Util.qll | 0 .../ql/{src => lib}/semmle/javascript/Variables.qll | 0 javascript/ql/{src => lib}/semmle/javascript/XML.qll | 0 javascript/ql/{src => lib}/semmle/javascript/YAML.qll | 0 .../semmle/javascript/dataflow/AbstractProperties.qll | 0 .../semmle/javascript/dataflow/AbstractValues.qll | 0 .../semmle/javascript/dataflow/BackwardExploration.qll | 0 .../semmle/javascript/dataflow/Configuration.qll | 0 .../dataflow/CustomAbstractValueDefinitions.qll | 0 .../{src => lib}/semmle/javascript/dataflow/DataFlow.qll | 0 .../semmle/javascript/dataflow/ForwardExploration.qll | 0 .../semmle/javascript/dataflow/InferredTypes.qll | 0 .../semmle/javascript/dataflow/LocalObjects.qll | 0 .../ql/{src => lib}/semmle/javascript/dataflow/Nodes.qll | 0 .../{src => lib}/semmle/javascript/dataflow/Portals.qll | 0 .../semmle/javascript/dataflow/Refinements.qll | 0 .../{src => lib}/semmle/javascript/dataflow/Sources.qll | 0 .../semmle/javascript/dataflow/TaintTracking.qll | 0 .../semmle/javascript/dataflow/TrackedNodes.qll | 0 .../semmle/javascript/dataflow/TypeInference.qll | 0 .../semmle/javascript/dataflow/TypeTracking.qll | 0 .../dataflow/internal/AbstractPropertiesImpl.qll | 0 .../javascript/dataflow/internal/AbstractValuesImpl.qll | 0 .../semmle/javascript/dataflow/internal/AccessPaths.qll | 0 .../javascript/dataflow/internal/AnalyzedParameters.qll | 0 .../dataflow/internal/BasicExprTypeInference.qll | 0 .../semmle/javascript/dataflow/internal/CallGraphs.qll | 0 .../semmle/javascript/dataflow/internal/DataFlowNode.qll | 0 .../semmle/javascript/dataflow/internal/FlowSteps.qll | 0 .../javascript/dataflow/internal/FunctionWrapperSteps.qll | 0 .../dataflow/internal/InterModuleTypeInference.qll | 0 .../dataflow/internal/InterProceduralTypeInference.qll | 0 .../javascript/dataflow/internal/PreCallGraphStep.qll | 0 .../dataflow/internal/PropertyTypeInference.qll | 0 .../semmle/javascript/dataflow/internal/StepSummary.qll | 0 .../dataflow/internal/VariableTypeInference.qll | 0 .../semmle/javascript/dependencies/Dependencies.qll | 0 .../javascript/dependencies/DependencyCustomizations.qll | 0 .../semmle/javascript/dependencies/FrameworkLibraries.qll | 0 .../semmle/javascript/dependencies/SemVer.qll | 0 .../semmle/javascript/explore/BackwardDataFlow.qll | 0 .../{src => lib}/semmle/javascript/explore/CallGraph.qll | 0 .../semmle/javascript/explore/ForwardDataFlow.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/AWS.qll | 0 .../semmle/javascript/frameworks/Angular2.qll | 0 .../semmle/javascript/frameworks/AngularJS.qll | 0 .../javascript/frameworks/AngularJS/AngularJSCore.qll | 0 .../frameworks/AngularJS/AngularJSExpressions.qll | 0 .../frameworks/AngularJS/DependencyInjections.qll | 0 .../frameworks/AngularJS/ServiceDefinitions.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Anser.qll | 0 .../semmle/javascript/frameworks/AsyncPackage.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Azure.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Babel.qll | 0 .../semmle/javascript/frameworks/Bundling.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Cheerio.qll | 0 .../semmle/javascript/frameworks/ClassValidator.qll | 0 .../semmle/javascript/frameworks/Classnames.qll | 0 .../semmle/javascript/frameworks/ClientRequests.qll | 0 .../semmle/javascript/frameworks/ClosureLibrary.qll | 0 .../semmle/javascript/frameworks/ComposedFunctions.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Connect.qll | 0 .../semmle/javascript/frameworks/ConnectExpressShared.qll | 0 .../semmle/javascript/frameworks/CookieLibraries.qll | 0 .../semmle/javascript/frameworks/Credentials.qll | 0 .../semmle/javascript/frameworks/CryptoLibraries.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/D3.qll | 0 .../semmle/javascript/frameworks/DateFunctions.qll | 0 .../semmle/javascript/frameworks/DigitalOcean.qll | 0 .../semmle/javascript/frameworks/Electron.qll | 0 .../semmle/javascript/frameworks/Emscripten.qll | 0 .../semmle/javascript/frameworks/EventEmitter.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Express.qll | 0 .../semmle/javascript/frameworks/ExpressModules.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Fastify.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Files.qll | 0 .../semmle/javascript/frameworks/Firebase.qll | 0 .../semmle/javascript/frameworks/FormParsers.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/GWT.qll | 0 .../{src => lib}/semmle/javascript/frameworks/GraphQL.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/HTTP.qll | 0 .../semmle/javascript/frameworks/Handlebars.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Hapi.qll | 0 .../{src => lib}/semmle/javascript/frameworks/History.qll | 0 .../semmle/javascript/frameworks/HttpFrameworks.qll | 0 .../semmle/javascript/frameworks/HttpProxy.qll | 0 .../semmle/javascript/frameworks/Immutable.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/JWT.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Knex.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Koa.qll | 0 .../semmle/javascript/frameworks/LazyCache.qll | 0 .../semmle/javascript/frameworks/LodashUnderscore.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Logging.qll | 0 .../semmle/javascript/frameworks/Markdown.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Micro.qll | 0 .../semmle/javascript/frameworks/MooTools.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Nest.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Next.qll | 0 .../{src => lib}/semmle/javascript/frameworks/NoSQL.qll | 0 .../semmle/javascript/frameworks/NodeJSLib.qll | 0 .../semmle/javascript/frameworks/PkgCloud.qll | 0 .../semmle/javascript/frameworks/Prettier.qll | 0 .../semmle/javascript/frameworks/PropertyProjection.qll | 0 .../semmle/javascript/frameworks/Puppeteer.qll | 0 .../{src => lib}/semmle/javascript/frameworks/React.qll | 0 .../semmle/javascript/frameworks/ReactNative.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Redux.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Request.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Restify.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/RxJS.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/SQL.qll | 0 .../semmle/javascript/frameworks/ServerLess.qll | 0 .../{src => lib}/semmle/javascript/frameworks/ShellJS.qll | 0 .../semmle/javascript/frameworks/SocketIO.qll | 0 .../semmle/javascript/frameworks/StringFormatters.qll | 0 .../javascript/frameworks/SystemCommandExecutors.qll | 0 .../semmle/javascript/frameworks/Templating.qll | 0 .../{src => lib}/semmle/javascript/frameworks/Testing.qll | 0 .../javascript/frameworks/TestingCustomizations.qll | 0 .../semmle/javascript/frameworks/TorrentLibraries.qll | 0 .../semmle/javascript/frameworks/Typeahead.qll | 0 .../semmle/javascript/frameworks/UriLibraries.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Vue.qll | 0 .../ql/{src => lib}/semmle/javascript/frameworks/Vuex.qll | 0 .../semmle/javascript/frameworks/WebSocket.qll | 0 .../semmle/javascript/frameworks/XmlParsers.qll | 0 .../{src => lib}/semmle/javascript/frameworks/jQuery.qll | 0 .../{src => lib}/semmle/javascript/frameworks/xUnit.qll | 0 .../semmle/javascript/heuristics/AdditionalFrameworks.qll | 0 .../semmle/javascript/heuristics/AdditionalPromises.qll | 0 .../javascript/heuristics/AdditionalRouteHandlers.qll | 0 .../semmle/javascript/heuristics/AdditionalSinks.qll | 0 .../semmle/javascript/heuristics/AdditionalSources.qll | 0 .../semmle/javascript/heuristics/AdditionalTaintSteps.qll | 0 .../semmle/javascript/heuristics/HeuristicSinks.qll | 0 .../semmle/javascript/heuristics/SyntacticHeuristics.qll | 0 .../ql/{src => lib}/semmle/javascript/heuristics/all.qll | 0 .../semmle/javascript/internal/CachedStages.qll | 0 .../semmle/javascript/internal/StmtContainers.qll | 0 .../ql/{src => lib}/semmle/javascript/linters/ESLint.qll | 0 .../ql/{src => lib}/semmle/javascript/linters/JSLint.qll | 0 .../ql/{src => lib}/semmle/javascript/linters/Linting.qll | 0 .../semmle/javascript/meta/ExtractionMetrics.qll | 0 .../semmle/javascript/security/CryptoAlgorithms.qll | 0 .../javascript/security/IncompleteBlacklistSanitizer.qll | 0 .../semmle/javascript/security/SensitiveActions.qll | 0 .../semmle/javascript/security/TaintedObject.qll | 0 .../javascript/security/TaintedObjectCustomizations.qll | 0 .../semmle/javascript/security/TaintedUrlSuffix.qll | 0 .../semmle/javascript/security/UselessUseOfCat.qll | 0 .../security/dataflow/BrokenCryptoAlgorithm.qll | 0 .../dataflow/BrokenCryptoAlgorithmCustomizations.qll | 0 .../security/dataflow/BrokenCryptoAlgorithmQuery.qll | 0 .../javascript/security/dataflow/BuildArtifactLeak.qll | 0 .../security/dataflow/BuildArtifactLeakCustomizations.qll | 0 .../security/dataflow/BuildArtifactLeakQuery.qll | 0 .../javascript/security/dataflow/CleartextLogging.qll | 0 .../security/dataflow/CleartextLoggingCustomizations.qll | 0 .../security/dataflow/CleartextLoggingQuery.qll | 0 .../javascript/security/dataflow/CleartextStorage.qll | 0 .../security/dataflow/CleartextStorageCustomizations.qll | 0 .../security/dataflow/CleartextStorageQuery.qll | 0 .../security/dataflow/ClientSideUrlRedirect.qll | 0 .../dataflow/ClientSideUrlRedirectCustomizations.qll | 0 .../security/dataflow/ClientSideUrlRedirectQuery.qll | 0 .../semmle/javascript/security/dataflow/CodeInjection.qll | 0 .../security/dataflow/CodeInjectionCustomizations.qll | 0 .../javascript/security/dataflow/CodeInjectionQuery.qll | 0 .../javascript/security/dataflow/CommandInjection.qll | 0 .../security/dataflow/CommandInjectionCustomizations.qll | 0 .../security/dataflow/CommandInjectionQuery.qll | 0 .../javascript/security/dataflow/ConditionalBypass.qll | 0 .../security/dataflow/ConditionalBypassCustomizations.qll | 0 .../security/dataflow/ConditionalBypassQuery.qll | 0 .../dataflow/CorsMisconfigurationForCredentials.qll | 0 .../CorsMisconfigurationForCredentialsCustomizations.qll | 0 .../dataflow/CorsMisconfigurationForCredentialsQuery.qll | 0 .../semmle/javascript/security/dataflow/DOM.qll | 0 .../security/dataflow/DeepObjectResourceExhaustion.qll | 0 .../DeepObjectResourceExhaustionCustomizations.qll | 0 .../dataflow/DeepObjectResourceExhaustionQuery.qll | 0 .../security/dataflow/DifferentKindsComparisonBypass.qll | 0 .../DifferentKindsComparisonBypassCustomizations.qll | 0 .../dataflow/DifferentKindsComparisonBypassQuery.qll | 0 .../semmle/javascript/security/dataflow/DomBasedXss.qll | 0 .../security/dataflow/DomBasedXssCustomizations.qll | 0 .../javascript/security/dataflow/DomBasedXssQuery.qll | 0 .../semmle/javascript/security/dataflow/ExceptionXss.qll | 0 .../javascript/security/dataflow/ExceptionXssQuery.qll | 0 .../dataflow/ExternalAPIUsedWithUntrustedData.qll | 0 .../ExternalAPIUsedWithUntrustedDataCustomizations.qll | 0 .../dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll | 0 .../javascript/security/dataflow/FileAccessToHttp.qll | 0 .../security/dataflow/FileAccessToHttpCustomizations.qll | 0 .../security/dataflow/FileAccessToHttpQuery.qll | 0 .../javascript/security/dataflow/HardcodedCredentials.qll | 0 .../dataflow/HardcodedCredentialsCustomizations.qll | 0 .../security/dataflow/HardcodedCredentialsQuery.qll | 0 .../security/dataflow/HardcodedDataInterpretedAsCode.qll | 0 .../HardcodedDataInterpretedAsCodeCustomizations.qll | 0 .../dataflow/HardcodedDataInterpretedAsCodeQuery.qll | 0 .../dataflow/HostHeaderPoisoningInEmailGeneration.qll | 0 .../HostHeaderPoisoningInEmailGenerationQuery.qll | 0 .../javascript/security/dataflow/HttpToFileAccess.qll | 0 .../security/dataflow/HttpToFileAccessCustomizations.qll | 0 .../security/dataflow/HttpToFileAccessQuery.qll | 0 .../security/dataflow/ImproperCodeSanitization.qll | 0 .../dataflow/ImproperCodeSanitizationCustomizations.qll | 0 .../security/dataflow/ImproperCodeSanitizationQuery.qll | 0 .../dataflow/IncompleteHtmlAttributeSanitization.qll | 0 .../IncompleteHtmlAttributeSanitizationCustomizations.qll | 0 .../dataflow/IncompleteHtmlAttributeSanitizationQuery.qll | 0 .../security/dataflow/IndirectCommandArgument.qll | 0 .../security/dataflow/IndirectCommandInjection.qll | 0 .../dataflow/IndirectCommandInjectionCustomizations.qll | 0 .../security/dataflow/IndirectCommandInjectionQuery.qll | 0 .../javascript/security/dataflow/InsecureDownload.qll | 0 .../security/dataflow/InsecureDownloadCustomizations.qll | 0 .../security/dataflow/InsecureDownloadQuery.qll | 0 .../javascript/security/dataflow/InsecureRandomness.qll | 0 .../dataflow/InsecureRandomnessCustomizations.qll | 0 .../security/dataflow/InsecureRandomnessQuery.qll | 0 .../security/dataflow/InsufficientPasswordHash.qll | 0 .../dataflow/InsufficientPasswordHashCustomizations.qll | 0 .../security/dataflow/InsufficientPasswordHashQuery.qll | 0 .../semmle/javascript/security/dataflow/LogInjection.qll | 0 .../javascript/security/dataflow/LogInjectionQuery.qll | 0 .../javascript/security/dataflow/LoopBoundInjection.qll | 0 .../dataflow/LoopBoundInjectionCustomizations.qll | 0 .../security/dataflow/LoopBoundInjectionQuery.qll | 0 .../javascript/security/dataflow/MissingRateLimiting.qll | 0 .../javascript/security/dataflow/NosqlInjection.qll | 0 .../security/dataflow/NosqlInjectionCustomizations.qll | 0 .../javascript/security/dataflow/NosqlInjectionQuery.qll | 0 .../javascript/security/dataflow/PostMessageStar.qll | 0 .../security/dataflow/PostMessageStarCustomizations.qll | 0 .../javascript/security/dataflow/PostMessageStarQuery.qll | 0 .../security/dataflow/PropertyInjectionShared.qll | 0 .../security/dataflow/PrototypePollutingAssignment.qll | 0 .../PrototypePollutingAssignmentCustomizations.qll | 0 .../dataflow/PrototypePollutingAssignmentQuery.qll | 0 .../javascript/security/dataflow/PrototypePollution.qll | 0 .../dataflow/PrototypePollutionCustomizations.qll | 0 .../security/dataflow/PrototypePollutionQuery.qll | 0 .../semmle/javascript/security/dataflow/ReflectedXss.qll | 0 .../security/dataflow/ReflectedXssCustomizations.qll | 0 .../javascript/security/dataflow/ReflectedXssQuery.qll | 0 .../javascript/security/dataflow/RegExpInjection.qll | 0 .../security/dataflow/RegExpInjectionCustomizations.qll | 0 .../javascript/security/dataflow/RegExpInjectionQuery.qll | 0 .../javascript/security/dataflow/RemoteFlowSources.qll | 0 .../security/dataflow/RemotePropertyInjection.qll | 0 .../dataflow/RemotePropertyInjectionCustomizations.qll | 0 .../security/dataflow/RemotePropertyInjectionQuery.qll | 0 .../javascript/security/dataflow/RequestForgery.qll | 0 .../security/dataflow/RequestForgeryCustomizations.qll | 0 .../javascript/security/dataflow/RequestForgeryQuery.qll | 0 .../security/dataflow/ServerSideUrlRedirect.qll | 0 .../dataflow/ServerSideUrlRedirectCustomizations.qll | 0 .../security/dataflow/ServerSideUrlRedirectQuery.qll | 0 .../dataflow/ShellCommandInjectionFromEnvironment.qll | 0 ...ShellCommandInjectionFromEnvironmentCustomizations.qll | 0 .../ShellCommandInjectionFromEnvironmentQuery.qll | 0 .../semmle/javascript/security/dataflow/SqlInjection.qll | 0 .../security/dataflow/SqlInjectionCustomizations.qll | 0 .../javascript/security/dataflow/SqlInjectionQuery.qll | 0 .../javascript/security/dataflow/StackTraceExposure.qll | 0 .../dataflow/StackTraceExposureCustomizations.qll | 0 .../security/dataflow/StackTraceExposureQuery.qll | 0 .../semmle/javascript/security/dataflow/StoredXss.qll | 0 .../javascript/security/dataflow/StoredXssQuery.qll | 0 .../javascript/security/dataflow/TaintedFormatString.qll | 0 .../dataflow/TaintedFormatStringCustomizations.qll | 0 .../security/dataflow/TaintedFormatStringQuery.qll | 0 .../semmle/javascript/security/dataflow/TaintedPath.qll | 0 .../security/dataflow/TaintedPathCustomizations.qll | 0 .../javascript/security/dataflow/TaintedPathQuery.qll | 0 .../security/dataflow/TemplateObjectInjection.qll | 0 .../dataflow/TemplateObjectInjectionCustomizations.qll | 0 .../security/dataflow/TemplateObjectInjectionQuery.qll | 0 .../dataflow/TypeConfusionThroughParameterTampering.qll | 0 ...peConfusionThroughParameterTamperingCustomizations.qll | 0 .../TypeConfusionThroughParameterTamperingQuery.qll | 0 .../security/dataflow/UnsafeDeserialization.qll | 0 .../dataflow/UnsafeDeserializationCustomizations.qll | 0 .../security/dataflow/UnsafeDeserializationQuery.qll | 0 .../security/dataflow/UnsafeDynamicMethodAccess.qll | 0 .../dataflow/UnsafeDynamicMethodAccessCustomizations.qll | 0 .../security/dataflow/UnsafeDynamicMethodAccessQuery.qll | 0 .../security/dataflow/UnsafeHtmlConstruction.qll | 0 .../dataflow/UnsafeHtmlConstructionCustomizations.qll | 0 .../security/dataflow/UnsafeHtmlConstructionQuery.qll | 0 .../javascript/security/dataflow/UnsafeJQueryPlugin.qll | 0 .../dataflow/UnsafeJQueryPluginCustomizations.qll | 0 .../security/dataflow/UnsafeJQueryPluginQuery.qll | 0 .../security/dataflow/UnsafeShellCommandConstruction.qll | 0 .../UnsafeShellCommandConstructionCustomizations.qll | 0 .../dataflow/UnsafeShellCommandConstructionQuery.qll | 0 .../security/dataflow/UnvalidatedDynamicMethodCall.qll | 0 .../UnvalidatedDynamicMethodCallCustomizations.qll | 0 .../dataflow/UnvalidatedDynamicMethodCallQuery.qll | 0 .../javascript/security/dataflow/UrlConcatenation.qll | 0 .../semmle/javascript/security/dataflow/XmlBomb.qll | 0 .../security/dataflow/XmlBombCustomizations.qll | 0 .../semmle/javascript/security/dataflow/XmlBombQuery.qll | 0 .../javascript/security/dataflow/XpathInjection.qll | 0 .../security/dataflow/XpathInjectionCustomizations.qll | 0 .../javascript/security/dataflow/XpathInjectionQuery.qll | 0 .../semmle/javascript/security/dataflow/Xss.qll | 0 .../semmle/javascript/security/dataflow/XssThroughDom.qll | 0 .../security/dataflow/XssThroughDomCustomizations.qll | 0 .../javascript/security/dataflow/XssThroughDomQuery.qll | 0 .../semmle/javascript/security/dataflow/Xxe.qll | 0 .../javascript/security/dataflow/XxeCustomizations.qll | 0 .../semmle/javascript/security/dataflow/XxeQuery.qll | 0 .../semmle/javascript/security/dataflow/ZipSlip.qll | 0 .../security/dataflow/ZipSlipCustomizations.qll | 0 .../semmle/javascript/security/dataflow/ZipSlipQuery.qll | 0 .../security/internal/SensitiveDataHeuristics.qll | 0 .../security/performance/ExponentialBackTracking.qll | 0 .../javascript/security/performance/PolynomialReDoS.qll | 0 .../performance/PolynomialReDoSCustomizations.qll | 0 .../semmle/javascript/security/performance/ReDoSUtil.qll | 0 .../javascript/security/performance/RegExpTreeView.qll | 0 .../security/performance/SuperlinearBackTracking.qll | 0 javascript/ql/{src => lib}/semmlecode.javascript.dbscheme | 0 .../ql/{src => lib}/semmlecode.javascript.dbscheme.stats | 0 .../ql/src/codeql-suites/javascript-code-scanning.qls | 2 +- javascript/ql/src/codeql-suites/javascript-lgtm-full.qls | 2 +- .../src/codeql-suites/javascript-security-and-quality.qls | 2 +- .../ql/src/codeql-suites/javascript-security-extended.qls | 2 +- javascript/ql/src/qlpack.lock.yml | 4 ++++ javascript/ql/src/qlpack.yml | 8 +++++--- javascript/ql/test/qlpack.lock.yml | 4 ++++ javascript/ql/test/qlpack.yml | 6 ++++-- javascript/upgrades/qlpack.lock.yml | 4 ++++ 410 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 javascript/ql/examples/qlpack.lock.yml rename javascript/ql/{src => lib}/Customizations.qll (100%) rename javascript/ql/{src => lib}/default.qll (100%) rename javascript/ql/{src => lib}/javascript.qll (100%) create mode 100644 javascript/ql/lib/qlpack.lock.yml create mode 100644 javascript/ql/lib/qlpack.yml rename javascript/ql/{src => lib}/semmle/files/FileSystem.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/AMD.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/AST.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Aliases.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/ApiGraphs.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Arrays.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Base64.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/BasicBlocks.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/CFG.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/CanonicalNames.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/CharacterEscapes.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Classes.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Closure.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Collections.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Comments.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Concepts.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Constants.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/DOM.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/DefUse.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/DefensiveProgramming.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/DynamicPropertyAccess.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/E4X.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/ES2015Modules.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/EmailClients.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Errors.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Expr.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Extend.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Externs.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Files.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Functions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/GeneratedCode.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Generators.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/GlobalAccessPaths.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/HTML.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/HtmlSanitizers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/InclusionTests.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JSDoc.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JSON.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JSX.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JsonParsers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JsonSchema.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/JsonStringifiers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Lines.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Locations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/MembershipCandidates.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Modules.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/NPM.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/NodeJS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/NodeModuleResolutionImpl.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/PackageExports.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Paths.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/PrintAst.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Promises.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/RangeAnalysis.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Regexp.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/RestrictedLocations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/SSA.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/SourceMaps.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/StandardLibrary.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Stmt.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/StringConcatenation.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/StringOps.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Templates.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Tokens.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/TypeAnnotations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/TypeScript.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Unit.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Util.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/Variables.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/XML.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/YAML.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/AbstractProperties.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/AbstractValues.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/BackwardExploration.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/Configuration.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/DataFlow.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/ForwardExploration.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/InferredTypes.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/LocalObjects.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/Nodes.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/Portals.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/Refinements.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/Sources.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/TaintTracking.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/TrackedNodes.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/TypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/TypeTracking.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/AccessPaths.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/AnalyzedParameters.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/CallGraphs.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/DataFlowNode.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/FlowSteps.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/PreCallGraphStep.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/PropertyTypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/StepSummary.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dataflow/internal/VariableTypeInference.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dependencies/Dependencies.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dependencies/DependencyCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dependencies/FrameworkLibraries.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/dependencies/SemVer.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/explore/BackwardDataFlow.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/explore/CallGraph.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/explore/ForwardDataFlow.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AWS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Angular2.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AngularJS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Anser.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/AsyncPackage.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Azure.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Babel.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Bundling.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Cheerio.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ClassValidator.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Classnames.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ClientRequests.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ClosureLibrary.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ComposedFunctions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Connect.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ConnectExpressShared.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/CookieLibraries.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Credentials.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/CryptoLibraries.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/D3.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/DateFunctions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/DigitalOcean.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Electron.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Emscripten.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/EventEmitter.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Express.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ExpressModules.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Fastify.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Files.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Firebase.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/FormParsers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/GWT.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/GraphQL.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/HTTP.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Handlebars.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Hapi.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/History.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/HttpFrameworks.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/HttpProxy.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Immutable.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/JWT.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Knex.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Koa.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/LazyCache.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/LodashUnderscore.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Logging.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Markdown.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Micro.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/MooTools.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Nest.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Next.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/NoSQL.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/NodeJSLib.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/PkgCloud.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Prettier.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/PropertyProjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Puppeteer.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/React.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ReactNative.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Redux.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Request.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Restify.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/RxJS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/SQL.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ServerLess.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/ShellJS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/SocketIO.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/StringFormatters.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/SystemCommandExecutors.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Templating.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Testing.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/TestingCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/TorrentLibraries.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Typeahead.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/UriLibraries.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Vue.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/Vuex.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/WebSocket.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/XmlParsers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/jQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/frameworks/xUnit.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalFrameworks.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalPromises.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalRouteHandlers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalSinks.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalSources.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/AdditionalTaintSteps.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/HeuristicSinks.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/SyntacticHeuristics.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/heuristics/all.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/internal/CachedStages.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/internal/StmtContainers.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/linters/ESLint.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/linters/JSLint.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/linters/Linting.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/meta/ExtractionMetrics.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/CryptoAlgorithms.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/IncompleteBlacklistSanitizer.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/SensitiveActions.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/TaintedObject.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/TaintedObjectCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/TaintedUrlSuffix.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/UselessUseOfCat.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BuildArtifactLeak.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextLogging.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextStorage.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CleartextStorageQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CodeInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CodeInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CommandInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CommandInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ConditionalBypass.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DOM.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DomBasedXss.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/DomBasedXssQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ExceptionXss.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ExceptionXssQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/FileAccessToHttp.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedCredentials.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HttpToFileAccess.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IndirectCommandArgument.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IndirectCommandInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureDownload.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureRandomness.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/LogInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/LogInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/LoopBoundInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/MissingRateLimiting.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/NosqlInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PostMessageStar.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PostMessageStarQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PropertyInjectionShared.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollution.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ReflectedXss.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ReflectedXssQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RegExpInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RemoteFlowSources.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RemotePropertyInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RequestForgery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/RequestForgeryQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/SqlInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/SqlInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/StackTraceExposure.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/StoredXss.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/StoredXssQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedFormatString.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedPath.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TaintedPathQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TemplateObjectInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDeserialization.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/UrlConcatenation.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XmlBomb.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XmlBombCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XmlBombQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XpathInjection.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XpathInjectionQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/Xss.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XssThroughDom.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XssThroughDomQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/Xxe.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XxeCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/XxeQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ZipSlip.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/dataflow/ZipSlipQuery.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/internal/SensitiveDataHeuristics.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/ExponentialBackTracking.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/PolynomialReDoS.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/ReDoSUtil.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/RegExpTreeView.qll (100%) rename javascript/ql/{src => lib}/semmle/javascript/security/performance/SuperlinearBackTracking.qll (100%) rename javascript/ql/{src => lib}/semmlecode.javascript.dbscheme (100%) rename javascript/ql/{src => lib}/semmlecode.javascript.dbscheme.stats (100%) create mode 100644 javascript/ql/src/qlpack.lock.yml create mode 100644 javascript/ql/test/qlpack.lock.yml create mode 100644 javascript/upgrades/qlpack.lock.yml diff --git a/javascript/ql/examples/qlpack.lock.yml b/javascript/ql/examples/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/examples/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/examples/qlpack.yml b/javascript/ql/examples/qlpack.yml index 3c498b497e1..cf0a9dc3e4c 100644 --- a/javascript/ql/examples/qlpack.yml +++ b/javascript/ql/examples/qlpack.yml @@ -1,3 +1,3 @@ name: codeql-javascript-examples version: 0.0.0 -libraryPathDependencies: codeql-javascript +libraryPathDependencies: codeql/javascript-all diff --git a/javascript/ql/src/Customizations.qll b/javascript/ql/lib/Customizations.qll similarity index 100% rename from javascript/ql/src/Customizations.qll rename to javascript/ql/lib/Customizations.qll diff --git a/javascript/ql/src/default.qll b/javascript/ql/lib/default.qll similarity index 100% rename from javascript/ql/src/default.qll rename to javascript/ql/lib/default.qll diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/lib/javascript.qll similarity index 100% rename from javascript/ql/src/javascript.qll rename to javascript/ql/lib/javascript.qll diff --git a/javascript/ql/lib/qlpack.lock.yml b/javascript/ql/lib/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/lib/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml new file mode 100644 index 00000000000..88e25a9852f --- /dev/null +++ b/javascript/ql/lib/qlpack.yml @@ -0,0 +1,7 @@ +name: codeql/javascript-all +version: 0.0.2 +dbscheme: semmlecode.javascript.dbscheme +extractor: javascript +library: true +dependencies: + codeql/javascript-upgrades: 0.0.2 diff --git a/javascript/ql/src/semmle/files/FileSystem.qll b/javascript/ql/lib/semmle/files/FileSystem.qll similarity index 100% rename from javascript/ql/src/semmle/files/FileSystem.qll rename to javascript/ql/lib/semmle/files/FileSystem.qll diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/lib/semmle/javascript/AMD.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/AMD.qll rename to javascript/ql/lib/semmle/javascript/AMD.qll diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/lib/semmle/javascript/AST.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/AST.qll rename to javascript/ql/lib/semmle/javascript/AST.qll diff --git a/javascript/ql/src/semmle/javascript/Aliases.qll b/javascript/ql/lib/semmle/javascript/Aliases.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Aliases.qll rename to javascript/ql/lib/semmle/javascript/Aliases.qll diff --git a/javascript/ql/src/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/ApiGraphs.qll rename to javascript/ql/lib/semmle/javascript/ApiGraphs.qll diff --git a/javascript/ql/src/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Arrays.qll rename to javascript/ql/lib/semmle/javascript/Arrays.qll diff --git a/javascript/ql/src/semmle/javascript/Base64.qll b/javascript/ql/lib/semmle/javascript/Base64.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Base64.qll rename to javascript/ql/lib/semmle/javascript/Base64.qll diff --git a/javascript/ql/src/semmle/javascript/BasicBlocks.qll b/javascript/ql/lib/semmle/javascript/BasicBlocks.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/BasicBlocks.qll rename to javascript/ql/lib/semmle/javascript/BasicBlocks.qll diff --git a/javascript/ql/src/semmle/javascript/CFG.qll b/javascript/ql/lib/semmle/javascript/CFG.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/CFG.qll rename to javascript/ql/lib/semmle/javascript/CFG.qll diff --git a/javascript/ql/src/semmle/javascript/CanonicalNames.qll b/javascript/ql/lib/semmle/javascript/CanonicalNames.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/CanonicalNames.qll rename to javascript/ql/lib/semmle/javascript/CanonicalNames.qll diff --git a/javascript/ql/src/semmle/javascript/CharacterEscapes.qll b/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/CharacterEscapes.qll rename to javascript/ql/lib/semmle/javascript/CharacterEscapes.qll diff --git a/javascript/ql/src/semmle/javascript/Classes.qll b/javascript/ql/lib/semmle/javascript/Classes.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Classes.qll rename to javascript/ql/lib/semmle/javascript/Classes.qll diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/lib/semmle/javascript/Closure.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Closure.qll rename to javascript/ql/lib/semmle/javascript/Closure.qll diff --git a/javascript/ql/src/semmle/javascript/Collections.qll b/javascript/ql/lib/semmle/javascript/Collections.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Collections.qll rename to javascript/ql/lib/semmle/javascript/Collections.qll diff --git a/javascript/ql/src/semmle/javascript/Comments.qll b/javascript/ql/lib/semmle/javascript/Comments.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Comments.qll rename to javascript/ql/lib/semmle/javascript/Comments.qll diff --git a/javascript/ql/src/semmle/javascript/Concepts.qll b/javascript/ql/lib/semmle/javascript/Concepts.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Concepts.qll rename to javascript/ql/lib/semmle/javascript/Concepts.qll diff --git a/javascript/ql/src/semmle/javascript/Constants.qll b/javascript/ql/lib/semmle/javascript/Constants.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Constants.qll rename to javascript/ql/lib/semmle/javascript/Constants.qll diff --git a/javascript/ql/src/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/DOM.qll rename to javascript/ql/lib/semmle/javascript/DOM.qll diff --git a/javascript/ql/src/semmle/javascript/DefUse.qll b/javascript/ql/lib/semmle/javascript/DefUse.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/DefUse.qll rename to javascript/ql/lib/semmle/javascript/DefUse.qll diff --git a/javascript/ql/src/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/DefensiveProgramming.qll rename to javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll diff --git a/javascript/ql/src/semmle/javascript/DynamicPropertyAccess.qll b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/DynamicPropertyAccess.qll rename to javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll diff --git a/javascript/ql/src/semmle/javascript/E4X.qll b/javascript/ql/lib/semmle/javascript/E4X.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/E4X.qll rename to javascript/ql/lib/semmle/javascript/E4X.qll diff --git a/javascript/ql/src/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/ES2015Modules.qll rename to javascript/ql/lib/semmle/javascript/ES2015Modules.qll diff --git a/javascript/ql/src/semmle/javascript/EmailClients.qll b/javascript/ql/lib/semmle/javascript/EmailClients.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/EmailClients.qll rename to javascript/ql/lib/semmle/javascript/EmailClients.qll diff --git a/javascript/ql/src/semmle/javascript/Errors.qll b/javascript/ql/lib/semmle/javascript/Errors.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Errors.qll rename to javascript/ql/lib/semmle/javascript/Errors.qll diff --git a/javascript/ql/src/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Expr.qll rename to javascript/ql/lib/semmle/javascript/Expr.qll diff --git a/javascript/ql/src/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Extend.qll rename to javascript/ql/lib/semmle/javascript/Extend.qll diff --git a/javascript/ql/src/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Externs.qll rename to javascript/ql/lib/semmle/javascript/Externs.qll diff --git a/javascript/ql/src/semmle/javascript/Files.qll b/javascript/ql/lib/semmle/javascript/Files.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Files.qll rename to javascript/ql/lib/semmle/javascript/Files.qll diff --git a/javascript/ql/src/semmle/javascript/Functions.qll b/javascript/ql/lib/semmle/javascript/Functions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Functions.qll rename to javascript/ql/lib/semmle/javascript/Functions.qll diff --git a/javascript/ql/src/semmle/javascript/GeneratedCode.qll b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/GeneratedCode.qll rename to javascript/ql/lib/semmle/javascript/GeneratedCode.qll diff --git a/javascript/ql/src/semmle/javascript/Generators.qll b/javascript/ql/lib/semmle/javascript/Generators.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Generators.qll rename to javascript/ql/lib/semmle/javascript/Generators.qll diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll rename to javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll diff --git a/javascript/ql/src/semmle/javascript/HTML.qll b/javascript/ql/lib/semmle/javascript/HTML.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/HTML.qll rename to javascript/ql/lib/semmle/javascript/HTML.qll diff --git a/javascript/ql/src/semmle/javascript/HtmlSanitizers.qll b/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/HtmlSanitizers.qll rename to javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll diff --git a/javascript/ql/src/semmle/javascript/InclusionTests.qll b/javascript/ql/lib/semmle/javascript/InclusionTests.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/InclusionTests.qll rename to javascript/ql/lib/semmle/javascript/InclusionTests.qll diff --git a/javascript/ql/src/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JSDoc.qll rename to javascript/ql/lib/semmle/javascript/JSDoc.qll diff --git a/javascript/ql/src/semmle/javascript/JSON.qll b/javascript/ql/lib/semmle/javascript/JSON.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JSON.qll rename to javascript/ql/lib/semmle/javascript/JSON.qll diff --git a/javascript/ql/src/semmle/javascript/JSX.qll b/javascript/ql/lib/semmle/javascript/JSX.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JSX.qll rename to javascript/ql/lib/semmle/javascript/JSX.qll diff --git a/javascript/ql/src/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JsonParsers.qll rename to javascript/ql/lib/semmle/javascript/JsonParsers.qll diff --git a/javascript/ql/src/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JsonSchema.qll rename to javascript/ql/lib/semmle/javascript/JsonSchema.qll diff --git a/javascript/ql/src/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/JsonStringifiers.qll rename to javascript/ql/lib/semmle/javascript/JsonStringifiers.qll diff --git a/javascript/ql/src/semmle/javascript/Lines.qll b/javascript/ql/lib/semmle/javascript/Lines.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Lines.qll rename to javascript/ql/lib/semmle/javascript/Lines.qll diff --git a/javascript/ql/src/semmle/javascript/Locations.qll b/javascript/ql/lib/semmle/javascript/Locations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Locations.qll rename to javascript/ql/lib/semmle/javascript/Locations.qll diff --git a/javascript/ql/src/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/MembershipCandidates.qll rename to javascript/ql/lib/semmle/javascript/MembershipCandidates.qll diff --git a/javascript/ql/src/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Modules.qll rename to javascript/ql/lib/semmle/javascript/Modules.qll diff --git a/javascript/ql/src/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/NPM.qll rename to javascript/ql/lib/semmle/javascript/NPM.qll diff --git a/javascript/ql/src/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/NodeJS.qll rename to javascript/ql/lib/semmle/javascript/NodeJS.qll diff --git a/javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll rename to javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll diff --git a/javascript/ql/src/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/PackageExports.qll rename to javascript/ql/lib/semmle/javascript/PackageExports.qll diff --git a/javascript/ql/src/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Paths.qll rename to javascript/ql/lib/semmle/javascript/Paths.qll diff --git a/javascript/ql/src/semmle/javascript/PrintAst.qll b/javascript/ql/lib/semmle/javascript/PrintAst.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/PrintAst.qll rename to javascript/ql/lib/semmle/javascript/PrintAst.qll diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Promises.qll rename to javascript/ql/lib/semmle/javascript/Promises.qll diff --git a/javascript/ql/src/semmle/javascript/RangeAnalysis.qll b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/RangeAnalysis.qll rename to javascript/ql/lib/semmle/javascript/RangeAnalysis.qll diff --git a/javascript/ql/src/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Regexp.qll rename to javascript/ql/lib/semmle/javascript/Regexp.qll diff --git a/javascript/ql/src/semmle/javascript/RestrictedLocations.qll b/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/RestrictedLocations.qll rename to javascript/ql/lib/semmle/javascript/RestrictedLocations.qll diff --git a/javascript/ql/src/semmle/javascript/SSA.qll b/javascript/ql/lib/semmle/javascript/SSA.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/SSA.qll rename to javascript/ql/lib/semmle/javascript/SSA.qll diff --git a/javascript/ql/src/semmle/javascript/SourceMaps.qll b/javascript/ql/lib/semmle/javascript/SourceMaps.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/SourceMaps.qll rename to javascript/ql/lib/semmle/javascript/SourceMaps.qll diff --git a/javascript/ql/src/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/StandardLibrary.qll rename to javascript/ql/lib/semmle/javascript/StandardLibrary.qll diff --git a/javascript/ql/src/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Stmt.qll rename to javascript/ql/lib/semmle/javascript/Stmt.qll diff --git a/javascript/ql/src/semmle/javascript/StringConcatenation.qll b/javascript/ql/lib/semmle/javascript/StringConcatenation.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/StringConcatenation.qll rename to javascript/ql/lib/semmle/javascript/StringConcatenation.qll diff --git a/javascript/ql/src/semmle/javascript/StringOps.qll b/javascript/ql/lib/semmle/javascript/StringOps.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/StringOps.qll rename to javascript/ql/lib/semmle/javascript/StringOps.qll diff --git a/javascript/ql/src/semmle/javascript/Templates.qll b/javascript/ql/lib/semmle/javascript/Templates.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Templates.qll rename to javascript/ql/lib/semmle/javascript/Templates.qll diff --git a/javascript/ql/src/semmle/javascript/Tokens.qll b/javascript/ql/lib/semmle/javascript/Tokens.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Tokens.qll rename to javascript/ql/lib/semmle/javascript/Tokens.qll diff --git a/javascript/ql/src/semmle/javascript/TypeAnnotations.qll b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/TypeAnnotations.qll rename to javascript/ql/lib/semmle/javascript/TypeAnnotations.qll diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/TypeScript.qll rename to javascript/ql/lib/semmle/javascript/TypeScript.qll diff --git a/javascript/ql/src/semmle/javascript/Unit.qll b/javascript/ql/lib/semmle/javascript/Unit.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Unit.qll rename to javascript/ql/lib/semmle/javascript/Unit.qll diff --git a/javascript/ql/src/semmle/javascript/Util.qll b/javascript/ql/lib/semmle/javascript/Util.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Util.qll rename to javascript/ql/lib/semmle/javascript/Util.qll diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/lib/semmle/javascript/Variables.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/Variables.qll rename to javascript/ql/lib/semmle/javascript/Variables.qll diff --git a/javascript/ql/src/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/XML.qll rename to javascript/ql/lib/semmle/javascript/XML.qll diff --git a/javascript/ql/src/semmle/javascript/YAML.qll b/javascript/ql/lib/semmle/javascript/YAML.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/YAML.qll rename to javascript/ql/lib/semmle/javascript/YAML.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/AbstractProperties.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/AbstractProperties.qll rename to javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/AbstractValues.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/AbstractValues.qll rename to javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll rename to javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/Configuration.qll rename to javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll b/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll rename to javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll rename to javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll rename to javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/InferredTypes.qll b/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/InferredTypes.qll rename to javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/LocalObjects.qll b/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/LocalObjects.qll rename to javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/Nodes.qll rename to javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/Portals.qll b/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/Portals.qll rename to javascript/ql/lib/semmle/javascript/dataflow/Portals.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/Refinements.qll b/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/Refinements.qll rename to javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/Sources.qll rename to javascript/ql/lib/semmle/javascript/dataflow/Sources.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll rename to javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/TrackedNodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/TrackedNodes.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/TrackedNodes.qll rename to javascript/ql/lib/semmle/javascript/dataflow/TrackedNodes.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/TypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll rename to javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AccessPaths.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/AccessPaths.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/AnalyzedParameters.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/AnalyzedParameters.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/DataFlowNode.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/DataFlowNode.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/FlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/FlowSteps.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/PreCallGraphStep.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/PreCallGraphStep.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/PropertyTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/PropertyTypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dataflow/internal/VariableTypeInference.qll rename to javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll diff --git a/javascript/ql/src/semmle/javascript/dependencies/Dependencies.qll b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dependencies/Dependencies.qll rename to javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll diff --git a/javascript/ql/src/semmle/javascript/dependencies/DependencyCustomizations.qll b/javascript/ql/lib/semmle/javascript/dependencies/DependencyCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dependencies/DependencyCustomizations.qll rename to javascript/ql/lib/semmle/javascript/dependencies/DependencyCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dependencies/FrameworkLibraries.qll rename to javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll diff --git a/javascript/ql/src/semmle/javascript/dependencies/SemVer.qll b/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/dependencies/SemVer.qll rename to javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll diff --git a/javascript/ql/src/semmle/javascript/explore/BackwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/explore/BackwardDataFlow.qll rename to javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll diff --git a/javascript/ql/src/semmle/javascript/explore/CallGraph.qll b/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/explore/CallGraph.qll rename to javascript/ql/lib/semmle/javascript/explore/CallGraph.qll diff --git a/javascript/ql/src/semmle/javascript/explore/ForwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/explore/ForwardDataFlow.qll rename to javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AWS.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AWS.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Angular2.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AngularJS.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Anser.qll b/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Anser.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Anser.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/AsyncPackage.qll b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/AsyncPackage.qll rename to javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Azure.qll b/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Azure.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Azure.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Babel.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Babel.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Bundling.qll b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Bundling.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Cheerio.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ClassValidator.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Classnames.qll b/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Classnames.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ClosureLibrary.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ClosureLibrary.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ComposedFunctions.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Connect.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Connect.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ConnectExpressShared.qll b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ConnectExpressShared.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/CookieLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/CookieLibraries.qll rename to javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Credentials.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/CryptoLibraries.qll rename to javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/D3.qll rename to javascript/ql/lib/semmle/javascript/frameworks/D3.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/DateFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/DateFunctions.qll rename to javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/DigitalOcean.qll b/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/DigitalOcean.qll rename to javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Electron.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Electron.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Emscripten.qll b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Emscripten.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/EventEmitter.qll rename to javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/lib/semmle/javascript/frameworks/Express.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Express.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Express.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ExpressModules.qll b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ExpressModules.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Fastify.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Files.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Files.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Firebase.qll b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Firebase.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/FormParsers.qll rename to javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/GWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/GWT.qll rename to javascript/ql/lib/semmle/javascript/frameworks/GWT.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/GraphQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/GraphQL.qll rename to javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/HTTP.qll rename to javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Handlebars.qll b/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Handlebars.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Hapi.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/History.qll rename to javascript/ql/lib/semmle/javascript/frameworks/History.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/HttpFrameworks.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/HttpFrameworks.qll rename to javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/HttpProxy.qll rename to javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Immutable.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/JWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/JWT.qll rename to javascript/ql/lib/semmle/javascript/frameworks/JWT.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Knex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Knex.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Knex.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Koa.qll b/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Koa.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Koa.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll rename to javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll rename to javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Logging.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Logging.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Markdown.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Micro.qll b/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Micro.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Micro.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/MooTools.qll b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/MooTools.qll rename to javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Nest.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Nest.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Next.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Next.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/NoSQL.qll rename to javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll rename to javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/PkgCloud.qll b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/PkgCloud.qll rename to javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Prettier.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll b/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/PropertyProjection.qll rename to javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Puppeteer.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/React.qll b/javascript/ql/lib/semmle/javascript/frameworks/React.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/React.qll rename to javascript/ql/lib/semmle/javascript/frameworks/React.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ReactNative.qll b/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ReactNative.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Redux.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Redux.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Request.qll b/javascript/ql/lib/semmle/javascript/frameworks/Request.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Request.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Request.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Restify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Restify.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Restify.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/RxJS.qll rename to javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/SQL.qll rename to javascript/ql/lib/semmle/javascript/frameworks/SQL.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ServerLess.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/ShellJS.qll rename to javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll rename to javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/StringFormatters.qll b/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/StringFormatters.qll rename to javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/SystemCommandExecutors.qll rename to javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Templating.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Templating.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Testing.qll b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Testing.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Testing.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/TestingCustomizations.qll b/javascript/ql/lib/semmle/javascript/frameworks/TestingCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/TestingCustomizations.qll rename to javascript/ql/lib/semmle/javascript/frameworks/TestingCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/TorrentLibraries.qll rename to javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Typeahead.qll b/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Typeahead.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/UriLibraries.qll rename to javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Vue.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Vue.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/Vuex.qll rename to javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/WebSocket.qll b/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/WebSocket.qll rename to javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll rename to javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/jQuery.qll rename to javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll diff --git a/javascript/ql/src/semmle/javascript/frameworks/xUnit.qll b/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/frameworks/xUnit.qll rename to javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalFrameworks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalFrameworks.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalPromises.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalPromises.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalRouteHandlers.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalSinks.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalSources.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalSources.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/AdditionalTaintSteps.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/AdditionalTaintSteps.qll rename to javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/HeuristicSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/HeuristicSinks.qll rename to javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/SyntacticHeuristics.qll b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/SyntacticHeuristics.qll rename to javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll diff --git a/javascript/ql/src/semmle/javascript/heuristics/all.qll b/javascript/ql/lib/semmle/javascript/heuristics/all.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/heuristics/all.qll rename to javascript/ql/lib/semmle/javascript/heuristics/all.qll diff --git a/javascript/ql/src/semmle/javascript/internal/CachedStages.qll b/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/internal/CachedStages.qll rename to javascript/ql/lib/semmle/javascript/internal/CachedStages.qll diff --git a/javascript/ql/src/semmle/javascript/internal/StmtContainers.qll b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/internal/StmtContainers.qll rename to javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll diff --git a/javascript/ql/src/semmle/javascript/linters/ESLint.qll b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/linters/ESLint.qll rename to javascript/ql/lib/semmle/javascript/linters/ESLint.qll diff --git a/javascript/ql/src/semmle/javascript/linters/JSLint.qll b/javascript/ql/lib/semmle/javascript/linters/JSLint.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/linters/JSLint.qll rename to javascript/ql/lib/semmle/javascript/linters/JSLint.qll diff --git a/javascript/ql/src/semmle/javascript/linters/Linting.qll b/javascript/ql/lib/semmle/javascript/linters/Linting.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/linters/Linting.qll rename to javascript/ql/lib/semmle/javascript/linters/Linting.qll diff --git a/javascript/ql/src/semmle/javascript/meta/ExtractionMetrics.qll b/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/meta/ExtractionMetrics.qll rename to javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll diff --git a/javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll rename to javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll diff --git a/javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/IncompleteBlacklistSanitizer.qll rename to javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll diff --git a/javascript/ql/src/semmle/javascript/security/SensitiveActions.qll b/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/SensitiveActions.qll rename to javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObject.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/TaintedObject.qll rename to javascript/ql/lib/semmle/javascript/security/TaintedObject.qll diff --git a/javascript/ql/src/semmle/javascript/security/TaintedObjectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/TaintedObjectCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/TaintedUrlSuffix.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/TaintedUrlSuffix.qll rename to javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll diff --git a/javascript/ql/src/semmle/javascript/security/UselessUseOfCat.qll b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/UselessUseOfCat.qll rename to javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithm.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeak.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeak.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeak.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLogging.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextLogging.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLogging.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorage.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorage.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorage.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CleartextStorageQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirect.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CodeInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CodeInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CommandInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CommandInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypass.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypass.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypass.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentials.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustion.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypass.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXss.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXss.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXssQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXss.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXss.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXss.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ExceptionXssQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedData.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttp.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttp.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttp.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentials.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentials.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentials.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCode.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGenerationQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccess.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccess.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccess.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitization.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitization.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandArgument.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandArgument.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownload.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownload.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownload.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomness.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomness.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomness.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHash.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LogInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/LogInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/LogInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LogInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/LogInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/LogInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/MissingRateLimiting.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStar.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStar.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStar.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PostMessageStarQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PropertyInjectionShared.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PropertyInjectionShared.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignment.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollution.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollution.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollution.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollution.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXss.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXss.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXss.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ReflectedXssQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RemoteFlowSources.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RequestForgery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/RequestForgeryQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirect.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironment.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/SqlInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/SqlInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposure.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposure.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposure.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXss.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/StoredXss.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/StoredXss.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/StoredXssQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatString.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatString.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatString.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPath.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPath.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTampering.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserialization.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserialization.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserialization.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccess.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstruction.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPlugin.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstruction.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCall.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/UrlConcatenation.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/UrlConcatenation.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBomb.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XmlBomb.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XmlBomb.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBombCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XmlBombCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XmlBombQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjection.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XpathInjection.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjection.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XpathInjectionQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDom.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDom.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDom.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XssThroughDomQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/Xxe.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/Xxe.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/Xxe.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XxeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XxeCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/XxeQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/XxeQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlip.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ZipSlip.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlip.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/dataflow/ZipSlipQuery.qll rename to javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll diff --git a/javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll b/javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll rename to javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/ExponentialBackTracking.qll b/javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/ExponentialBackTracking.qll rename to javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoS.qll b/javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoS.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoS.qll rename to javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoS.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll rename to javascript/ql/lib/semmle/javascript/security/performance/PolynomialReDoSCustomizations.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll rename to javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/RegExpTreeView.qll b/javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/RegExpTreeView.qll rename to javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll diff --git a/javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll b/javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll similarity index 100% rename from javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll rename to javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/lib/semmlecode.javascript.dbscheme similarity index 100% rename from javascript/ql/src/semmlecode.javascript.dbscheme rename to javascript/ql/lib/semmlecode.javascript.dbscheme diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/lib/semmlecode.javascript.dbscheme.stats similarity index 100% rename from javascript/ql/src/semmlecode.javascript.dbscheme.stats rename to javascript/ql/lib/semmlecode.javascript.dbscheme.stats diff --git a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls index 8ec0309619d..731cc41f8fb 100644 --- a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls +++ b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls @@ -1,4 +1,4 @@ - description: Standard Code Scanning queries for JavaScript -- qlpack: codeql-javascript +- queries: . - apply: code-scanning-selectors.yml from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls index b4336c666ae..5c8e26acaed 100644 --- a/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls +++ b/javascript/ql/src/codeql-suites/javascript-lgtm-full.qls @@ -1,5 +1,5 @@ - description: Standard LGTM queries for JavaScript, including ones not displayed by default -- qlpack: codeql-javascript +- queries: . - apply: lgtm-selectors.yml from: codeql/suite-helpers # These are only for IDE use. diff --git a/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls b/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls index 4d64a6e7a52..fe0fb9b6f34 100644 --- a/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls +++ b/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls @@ -1,4 +1,4 @@ - description: Security-and-quality queries for JavaScript -- qlpack: codeql-javascript +- queries: . - apply: security-and-quality-selectors.yml from: codeql/suite-helpers diff --git a/javascript/ql/src/codeql-suites/javascript-security-extended.qls b/javascript/ql/src/codeql-suites/javascript-security-extended.qls index ea78d5a0f05..6428ee80c48 100644 --- a/javascript/ql/src/codeql-suites/javascript-security-extended.qls +++ b/javascript/ql/src/codeql-suites/javascript-security-extended.qls @@ -1,4 +1,4 @@ - description: Security-extended queries for JavaScript -- qlpack: codeql-javascript +- queries: . - apply: security-extended-selectors.yml from: codeql/suite-helpers diff --git a/javascript/ql/src/qlpack.lock.yml b/javascript/ql/src/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/src/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 7612a1d52f2..2f4c7b5802f 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,7 @@ -name: codeql-javascript -version: 0.0.0 -dbscheme: semmlecode.javascript.dbscheme +name: codeql/javascript-queries +version: 0.0.2 suites: codeql-suites extractor: javascript +dependencies: + codeql/javascript-all: ^0.0.2 + codeql/suite-helpers: ^0.0.2 diff --git a/javascript/ql/test/qlpack.lock.yml b/javascript/ql/test/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/ql/test/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 diff --git a/javascript/ql/test/qlpack.yml b/javascript/ql/test/qlpack.yml index b60f895f131..d9d8aecb80d 100644 --- a/javascript/ql/test/qlpack.yml +++ b/javascript/ql/test/qlpack.yml @@ -1,5 +1,7 @@ -name: codeql-javascript-tests +name: codeql/javascript-tests version: 0.0.0 -libraryPathDependencies: codeql-javascript +dependencies: + codeql/javascript-all: "*" + codeql/javascript-queries: "*" extractor: javascript tests: . diff --git a/javascript/upgrades/qlpack.lock.yml b/javascript/upgrades/qlpack.lock.yml new file mode 100644 index 00000000000..06dd07fc7dc --- /dev/null +++ b/javascript/upgrades/qlpack.lock.yml @@ -0,0 +1,4 @@ +--- +dependencies: {} +compiled: false +lockVersion: 1.0.0 From 5609c3d1b58c6acd86894ae0e853022dd97d6c93 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 24 Aug 2021 16:11:33 -0700 Subject: [PATCH 353/429] Packaging: Fix identical files script --- config/identical-files.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/identical-files.json b/config/identical-files.json index 2b8faf0435d..037b0126cb3 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -382,7 +382,7 @@ "cpp/ql/lib/semmle/code/cpp/XML.qll", "csharp/ql/lib/semmle/code/csharp/XML.qll", "java/ql/lib/semmle/code/xml/XML.qll", - "javascript/ql/src/semmle/javascript/XML.qll", + "javascript/ql/lib/semmle/javascript/XML.qll", "python/ql/lib/semmle/python/xml/XML.qll" ], "DuplicationProblems.inc.qhelp": [ @@ -443,23 +443,23 @@ "csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll" ], "CryptoAlgorithms Python/JS": [ - "javascript/ql/src/semmle/javascript/security/CryptoAlgorithms.qll", + "javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll", "python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll" ], "SensitiveDataHeuristics Python/JS": [ - "javascript/ql/src/semmle/javascript/security/internal/SensitiveDataHeuristics.qll", + "javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll", "python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll" ], "ReDoS Util Python/JS": [ - "javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll", + "javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll", "python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll" ], "ReDoS Exponential Python/JS": [ - "javascript/ql/src/semmle/javascript/security/performance/ExponentialBackTracking.qll", + "javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll", "python/ql/lib/semmle/python/security/performance/ExponentialBackTracking.qll" ], "ReDoS Polynomial Python/JS": [ - "javascript/ql/src/semmle/javascript/security/performance/SuperlinearBackTracking.qll", + "javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll", "python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll" ] } From 0cc19d914e32be91c54dfcc7359e3475b9623502 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 25 Aug 2021 14:54:09 +0200 Subject: [PATCH 354/429] use toUnicode in ReDoSUtil.qll --- .../semmle/javascript/security/performance/ReDoSUtil.qll | 7 +------ .../lib/semmle/python/security/performance/ReDoSUtil.qll | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 3bdd47470fb..43601b1d407 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -422,12 +422,7 @@ private module CharacterClasses { 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) - ) + char = [" ", "\t", "\r", "\n", 11.toUnicode(), 12.toUnicode()] // 11.toUnicode() = \v, 12.toUnicode() = \f or clazz = "w" and char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_) diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index 3bdd47470fb..43601b1d407 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -422,12 +422,7 @@ private module CharacterClasses { 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) - ) + char = [" ", "\t", "\r", "\n", 11.toUnicode(), 12.toUnicode()] // 11.toUnicode() = \v, 12.toUnicode() = \f or clazz = "w" and char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".charAt(_) From b8ce5a63c5b9bc95724119542a3ba4713a975dc7 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 25 Aug 2021 17:33:45 -0500 Subject: [PATCH 355/429] Remove unncessary results Simplifies query to improve performance by removing unnecessary results. --- .../ql/src/experimental/Security/CWE-079/ClipboardXss.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql b/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql index e8cd8ac81e4..c6ae4e1fed6 100644 --- a/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql +++ b/javascript/ql/src/experimental/Security/CWE-079/ClipboardXss.ql @@ -23,7 +23,7 @@ import DataFlow::PathGraph SourceNode clipboardDataTransferSource(TypeTracker t) { t.start() and - exists(DataFlow::PropRead pr | pr.getPropertyName() = "clipboardData" and pr.flowsTo(result)) + exists(DataFlow::PropRead pr | pr.getPropertyName() = "clipboardData" and result = pr) or exists(TypeTracker t2 | result = clipboardDataTransferSource(t2).track(t2, t)) } @@ -39,7 +39,7 @@ SourceNode clipboardDataTransferSource() { SourceNode clipboardDataSource(TypeTracker t) { t.start() and - clipboardDataTransferSource().getAMethodCall("getData").flowsTo(result) + result = clipboardDataTransferSource().getAMethodCall("getData") or exists(TypeTracker t2 | result = clipboardDataSource(t2).track(t2, t)) } From 1dd4bf00acf99deee3b2d9d7ca92eb80f7476a05 Mon Sep 17 00:00:00 2001 From: Fosstars Date: Thu, 26 Aug 2021 09:41:05 +0200 Subject: [PATCH 356/429] Simplify StaticInitializationVectorSource Co-authored-by: Chris Smowton --- .../code/java/security/StaticInitializationVectorQuery.qll | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll index 119e457bb3f..5d88d620c21 100644 --- a/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/src/experimental/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -11,7 +11,7 @@ private predicate initializedWithConstants(ArrayCreationExpr array) { or // creating a multidimensional array with an initializer like `{ new byte[8], new byte[16] }` // This works around https://github.com/github/codeql/issues/6552 -- change me once there is - // a better way to distinguish nested initializers that create zero-filled arrays + // a better way to distinguish nested initializers that create zero-filled arrays // (e.g. `new byte[1]`) from those with an initializer list (`new byte[] { 1 }` or just `{ 1 }`) array.getInit().getAnInit().getAChildExpr() instanceof IntegerLiteral or @@ -85,9 +85,7 @@ private class ArrayUpdateConfig extends TaintTracking2::Configuration { private class StaticInitializationVectorSource extends DataFlow::Node { StaticInitializationVectorSource() { exists(StaticByteArrayCreation array | array = this.asExpr() | - not exists(ArrayUpdate update, ArrayUpdateConfig config | - config.hasFlow(DataFlow2::exprNode(array), DataFlow2::exprNode(update.getArray())) - ) + not exists(ArrayUpdateConfig config | config.hasFlow(DataFlow2::exprNode(array), _)) ) } } From 4e2c148e8017a83182ac98d75ed8244db81a6c76 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Thu, 26 Aug 2021 12:06:47 +0200 Subject: [PATCH 357/429] Model Objects API as CSV --- .../semmle/code/java/frameworks/Objects.qll | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 java/ql/lib/semmle/code/java/frameworks/Objects.qll diff --git a/java/ql/lib/semmle/code/java/frameworks/Objects.qll b/java/ql/lib/semmle/code/java/frameworks/Objects.qll new file mode 100644 index 00000000000..60d9d3afac5 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/Objects.qll @@ -0,0 +1,19 @@ +/** Definitions of taint steps in Objects class of the JDK */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class ObjectsSummaryCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + //`namespace; type; subtypes; name; signature; ext; input; output; kind` + "java.util;Objects;false;requireNonNull;;;Argument[0];ReturnValue;value", + "java.util;Objects;false;requireNonNullElse;;;Argument[0];ReturnValue;value", + "java.util;Objects;false;requireNonNullElse;;;Argument[1];ReturnValue;value", + "java.util;Objects;false;requireNonNullElseGet;;;Argument[0];ReturnValue;value", + "java.util;Objects;false;requireNonNullElseGet;;;Argument[1];ReturnValue;value", + "java.util;Objects;false;toString;;;Argument[1];ReturnValue;value" + ] + } +} From 8abb9fb0457e7f9a85345b77ab7fd698b78ae241 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Thu, 26 Aug 2021 12:06:56 +0200 Subject: [PATCH 358/429] Replace Objects model --- .../code/java/dataflow/ExternalFlow.qll | 1 + .../semmle/code/java/dataflow/FlowSteps.qll | 21 ------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index 1a532bf9b58..de6143154f4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -87,6 +87,7 @@ private module Frameworks { private import semmle.code.java.frameworks.JaxWS private import semmle.code.java.frameworks.JoddJson private import semmle.code.java.frameworks.JsonJava + private import semmle.code.java.frameworks.Objects private import semmle.code.java.frameworks.Optional private import semmle.code.java.frameworks.spring.SpringCache private import semmle.code.java.frameworks.spring.SpringHttp diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index 77bf4625207..5c58658cffd 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -50,27 +50,6 @@ abstract class FluentMethod extends ValuePreservingMethod { override predicate returnsValue(int arg) { arg = -1 } } -private class StandardLibraryValuePreservingMethod extends ValuePreservingMethod { - int returnsArgNo; - - StandardLibraryValuePreservingMethod() { - this.getDeclaringType().hasQualifiedName("java.util", "Objects") and - ( - this.hasName(["requireNonNull", "requireNonNullElseGet"]) and returnsArgNo = 0 - or - this.hasName("requireNonNullElse") and returnsArgNo = [0 .. this.getNumberOfParameters() - 1] - or - this.hasName("toString") and returnsArgNo = 1 - ) - or - this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.util", "Stack") and - this.hasName("push") and - returnsArgNo = 0 - } - - override predicate returnsValue(int argNo) { argNo = returnsArgNo } -} - /** * A unit class for adding additional taint steps. * From 10bc2568b7ae35579f78f53df2a2b5d5dba08e7c Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Tue, 24 Aug 2021 17:05:33 +0100 Subject: [PATCH 359/429] C++: Add support for default member initializers. --- .../dataflow/fields/dataflow-consistency.expected | 4 ++++ 1 file changed, 4 insertions(+) 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 8cc13f226a9..8333b9d5776 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -1,4 +1,8 @@ uniqueEnclosingCallable +| C.cpp:9:14:9:23 | 0 | Node should have one enclosing callable but has 0. | +| C.cpp:9:14:9:23 | new | Node should have one enclosing callable but has 0. | +| C.cpp:10:20:10:29 | 0 | Node should have one enclosing callable but has 0. | +| C.cpp:10:20:10:29 | new | Node should have one enclosing callable but has 0. | | C.cpp:37:24:37:33 | 0 | Node should have one enclosing callable but has 0. | | C.cpp:37:24:37:33 | new | Node should have one enclosing callable but has 0. | uniqueType From 592a42231fad8c90b289b272ae5e41ce5f972340 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 26 Aug 2021 13:46:47 +0200 Subject: [PATCH 360/429] C#: Fix test for `InsecureSQLConnection.ql` --- .../InsecureSQLConnection/InsecureSQLConnection.cs | 6 +++--- .../InsecureSQLConnection.expected | 13 +++++++++++++ .../InsecureSQLConnection.qlref | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.cs b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.cs index c57499a14ce..826c88fff73 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.cs @@ -34,7 +34,7 @@ namespace InsecureSQLConnection public void TriggerThis() { - // BAD, Encrypt not specified [NOT DETECTED] + // BAD, Encrypt not specified SqlConnection conn = new SqlConnection("Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;"); } @@ -42,7 +42,7 @@ namespace InsecureSQLConnection { string connectString = "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd"; - // BAD, Encrypt not specified [NOT DETECTED] + // BAD, Encrypt not specified SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); var conn = new SqlConnection(builder.ConnectionString); } @@ -51,7 +51,7 @@ namespace InsecureSQLConnection { string connectString = "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false"; - // BAD, Encrypt set to false [NOT DETECTED] + // BAD, Encrypt set to false SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectString); var conn = new SqlConnection(builder.ConnectionString); } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.expected b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.expected index e69de29bb2d..819cebbd064 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.expected @@ -0,0 +1,13 @@ +edges +| InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | +| InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | +nodes +| InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | semmle.label | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | +| InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | +| InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | semmle.label | access to local variable connectString | +| InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | semmle.label | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | +| InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | semmle.label | access to local variable connectString | +#select +| InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | $@ flows to here and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:38:52:38:128 | "Server=myServerName\\myInstanceName;Database=myDataBase;User Id=myUsername;" | Connection string | +| InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" : String | InsecureSQLConnection.cs:46:81:46:93 | access to local variable connectString | $@ flows to here and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:44:17:44:64 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd" | Connection string | +| InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" : String | InsecureSQLConnection.cs:55:81:55:93 | access to local variable connectString | $@ flows to here and does not specify `Encrypt=True`. | InsecureSQLConnection.cs:53:17:53:78 | "Server=1.2.3.4;Database=Anything;UID=ab;Pwd=cd;Encrypt=false" | Connection string | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.qlref b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.qlref index e3b1776a3fb..9809e87e73c 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.qlref +++ b/csharp/ql/test/query-tests/Security Features/CWE-327/InsecureSQLConnection/InsecureSQLConnection.qlref @@ -1 +1 @@ -Security Features/CWE-091/XMLInjection.ql \ No newline at end of file +Security Features/CWE-327/InsecureSQLConnection.ql \ No newline at end of file From 7e1efbdd8edef71d6a374cab24ef2027d98e3754 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 26 Aug 2021 13:48:14 +0200 Subject: [PATCH 361/429] C#: Use data flow instead of taint tracking in `InsecureSQLConnection.ql` --- .../ql/src/Security Features/CWE-327/InsecureSQLConnection.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index fd4a37f7ee3..25c8ea6ef89 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -14,9 +14,9 @@ import csharp import DataFlow::PathGraph /** - * A `DataFlow::Configuration` for tracking `Strings passed to SqlConnectionStringBuilder` instances. + * A data flow configuration for tracking strings passed to `SqlConnection[StringBuilder]` instances. */ -class TaintTrackingConfiguration extends TaintTracking::Configuration { +class TaintTrackingConfiguration extends DataFlow::Configuration { TaintTrackingConfiguration() { this = "TaintTrackingConfiguration" } override predicate isSource(DataFlow::Node source) { From 9ca3b4661a2fd8f47b8a08bc728f6c671a919946 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Thu, 26 Aug 2021 14:03:55 +0200 Subject: [PATCH 362/429] Fix return value for `requireNonNullElse ` Co-authored-by: Chris Smowton --- java/ql/lib/semmle/code/java/frameworks/Objects.qll | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/Objects.qll b/java/ql/lib/semmle/code/java/frameworks/Objects.qll index 60d9d3afac5..acb0aa6e1cf 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Objects.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Objects.qll @@ -9,10 +9,8 @@ private class ObjectsSummaryCsv extends SummaryModelCsv { [ //`namespace; type; subtypes; name; signature; ext; input; output; kind` "java.util;Objects;false;requireNonNull;;;Argument[0];ReturnValue;value", - "java.util;Objects;false;requireNonNullElse;;;Argument[0];ReturnValue;value", - "java.util;Objects;false;requireNonNullElse;;;Argument[1];ReturnValue;value", + "java.util;Objects;false;requireNonNullElse;;;Argument[0..1];ReturnValue;value", "java.util;Objects;false;requireNonNullElseGet;;;Argument[0];ReturnValue;value", - "java.util;Objects;false;requireNonNullElseGet;;;Argument[1];ReturnValue;value", "java.util;Objects;false;toString;;;Argument[1];ReturnValue;value" ] } From 29e75aed750966f388d886b911d06b859f66bd5a Mon Sep 17 00:00:00 2001 From: Edoardo Pirovano Date: Thu, 26 Aug 2021 15:54:54 +0100 Subject: [PATCH 363/429] JS: Release new version of library and upgrade pack --- javascript/ql/lib/qlpack.yml | 4 ++-- javascript/upgrades/qlpack.yml | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 88e25a9852f..7b457a2789f 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,7 +1,7 @@ name: codeql/javascript-all -version: 0.0.2 +version: 0.0.3 dbscheme: semmlecode.javascript.dbscheme extractor: javascript library: true dependencies: - codeql/javascript-upgrades: 0.0.2 + codeql/javascript-upgrades: 0.0.3 diff --git a/javascript/upgrades/qlpack.yml b/javascript/upgrades/qlpack.yml index e28efab120f..58956fde2eb 100644 --- a/javascript/upgrades/qlpack.yml +++ b/javascript/upgrades/qlpack.yml @@ -1,2 +1,4 @@ -name: codeql-javascript-upgrades +name: codeql/javascript-upgrades upgrades: . +library: true +version: 0.0.3 From 33c727e6b9faaedb79765e7b41ecbeab237bce6c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Aug 2021 15:05:25 +0100 Subject: [PATCH 364/429] Split up GenerateFlowTestCase.qll This doesn't change any behaviour or alter any predicate bodies --- java/ql/src/utils/FlowTestCase.qll | 322 ++++++++++++ .../src/utils/FlowTestCaseSupportMethods.qll | 52 ++ java/ql/src/utils/FlowTestCaseUtils.qll | 127 +++++ java/ql/src/utils/GenerateFlowTestCase.qll | 487 +----------------- 4 files changed, 504 insertions(+), 484 deletions(-) create mode 100644 java/ql/src/utils/FlowTestCase.qll create mode 100644 java/ql/src/utils/FlowTestCaseSupportMethods.qll create mode 100644 java/ql/src/utils/FlowTestCaseUtils.qll diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll new file mode 100644 index 00000000000..2ae19a804e9 --- /dev/null +++ b/java/ql/src/utils/FlowTestCase.qll @@ -0,0 +1,322 @@ +import java +private import semmle.code.java.dataflow.internal.DataFlowUtil +private import semmle.code.java.dataflow.ExternalFlow +private import semmle.code.java.dataflow.FlowSummary +private import semmle.code.java.dataflow.internal.FlowSummaryImpl +private import FlowTestCaseUtils +private import FlowTestCaseSupportMethods + +/** + * A CSV row to generate tests for. Users should extend this to define which + * tests to generate. Rows specified here should also satisfy `SummaryModelCsv.row`. + */ +class TargetSummaryModelCsv extends Unit { + /** + * Holds if a test should be generated for `row`. + */ + abstract predicate row(string r); +} + +/** + * Gets a CSV row for which a test has been requested, but `SummaryModelCsv.row` does not hold of it. + */ +query string missingSummaryModelCsv() { + any(TargetSummaryModelCsv target).row(result) and + not any(SummaryModelCsv model).row(result) +} + +/** + * Returns type of parameter `i` of `callable`, including the type of `this` for parameter -1. + */ +Type getParameterType(CallableToTest callable, int i) { + if i = -1 then result = callable.getDeclaringType() else result = callable.getParameterType(i) +} + +private class CallableToTest extends Callable { + CallableToTest() { + exists( + string namespace, string type, boolean subtypes, string name, string signature, string ext + | + summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _) and + this = interpretElement(namespace, type, subtypes, name, signature, ext) and + this.isPublic() and + getRootType(this.getDeclaringType()).isPublic() + ) + } +} + +/** + * A test snippet (a fragment of Java code that checks that `row` causes `callable` to propagate value/taint (according to `preservesValue`) + * from `input` to `output`). Usually there is one of these per CSV row (`row`), but there may be more if `row` describes more than one + * override or overload of a particular method, or if the input or output specifications cover more than one argument. + */ +private newtype TTestCase = + MkTestCase( + CallableToTest callable, SummaryComponentStack input, SummaryComponentStack output, string kind, + string row + ) { + exists( + string namespace, string type, boolean subtypes, string name, string signature, string ext, + string inputSpec, string outputSpec + | + any(TargetSummaryModelCsv tsmc).row(row) and + summaryModel(namespace, type, subtypes, name, signature, ext, inputSpec, outputSpec, kind, row) and + callable = interpretElement(namespace, type, subtypes, name, signature, ext) and + Private::External::interpretSpec(inputSpec, input) and + Private::External::interpretSpec(outputSpec, output) + ) + } + +/** + * A test snippet (as `TTestCase`, except `baseInput` and `baseOutput` hold the bottom of the summary stacks + * `input` and `output` respectively (hence, `baseInput` and `baseOutput` are parameters or return values). + */ +class TestCase extends TTestCase { + CallableToTest callable; + SummaryComponentStack input; + SummaryComponentStack output; + SummaryComponentStack baseInput; + SummaryComponentStack baseOutput; + string kind; + string row; + + TestCase() { + this = MkTestCase(callable, input, output, kind, row) and + baseInput = input.drop(input.length() - 1) and + baseOutput = output.drop(output.length() - 1) + } + + /** + * Returns a representation of this test case's parameters suitable for debugging. + */ + string toString() { + result = + row + " / " + callable + " / " + input + " / " + output + " / " + baseInput + " / " + + baseOutput + " / " + kind + } + + /** + * Returns a value to pass as `callable`'s `argIdx`th argument whose value is irrelevant to the test + * being generated. This will be a zero or a null value, perhaps typecast if we need to disambiguate overloads. + */ + string getFiller(int argIdx) { + exists(Type t | t = callable.getParameterType(argIdx) | + t instanceof RefType and + ( + if mayBeAmbiguous(callable) + then result = "(" + getShortNameIfPossible(t) + ")null" + else result = "null" + ) + or + result = getZero(t) + ) + } + + /** + * Returns the value to pass for `callable`'s `i`th argument, which may be `in` if this is the input argument for + * this test, `out` if it is the output, `instance` if this is an instance method and the instance is neither the + * input nor the output, or a zero/null filler value otherwise. + */ + string getArgument(int i) { + (i = -1 or exists(callable.getParameter(i))) and + if baseInput = SummaryComponentStack::argument(i) + then result = "in" + else + if baseOutput = SummaryComponentStack::argument(i) + then result = "out" + else + if i = -1 + then result = "instance" + else result = this.getFiller(i) + } + + /** + * Returns a statement invoking `callable`, passing `input` and capturing `output` as needed. + */ + string makeCall() { + // For example, one of: + // out = in.method(filler); + // or + // out = filler.method(filler, in, filler); + // or + // out = Type.method(filler, in, filler); + // or + // filler.method(filler, in, out, filler); + // or + // Type.method(filler, in, out, filler); + // or + // out = new Type(filler, in, filler); + // or + // new Type(filler, in, out, filler); + // or + // in.method(filler, out, filler); + // or + // out.method(filler, in, filler); + exists(string storePrefix, string invokePrefix, string args | + ( + if + baseOutput = SummaryComponentStack::return() + or + callable instanceof Constructor and baseOutput = SummaryComponentStack::argument(-1) + then storePrefix = "out = " + else storePrefix = "" + ) and + ( + if callable instanceof Constructor + then invokePrefix = "new " + else + if callable.(Method).isStatic() + then invokePrefix = getShortNameIfPossible(callable.getDeclaringType()) + "." + else invokePrefix = this.getArgument(-1) + "." + ) and + args = concat(int i | i >= 0 | this.getArgument(i), ", " order by i) and + result = storePrefix + invokePrefix + callable.getName() + "(" + args + ")" + ) + } + + /** + * Returns an inline test expectation appropriate to this CSV row. + */ + string getExpectation() { + kind = "value" and result = "// $ hasValueFlow" + or + kind = "taint" and result = "// $ hasTaintFlow" + } + + /** + * Returns a declaration and initialisation of a variable named `instance` if required; otherwise returns an empty string. + */ + string getInstancePrefix() { + if + callable instanceof Method and + not callable.(Method).isStatic() and + baseOutput != SummaryComponentStack::argument(-1) and + baseInput != SummaryComponentStack::argument(-1) + then + // In this case `out` is the instance. + result = getShortNameIfPossible(callable.getDeclaringType()) + " instance = null;\n\t\t\t" + else result = "" + } + + /** + * Returns the type of the output for this test. + */ + Type getOutputType() { + if baseOutput = SummaryComponentStack::return() + then result = callable.getReturnType() + else + exists(int i | + baseOutput = SummaryComponentStack::argument(i) and + result = getParameterType(callable, i) + ) + } + + /** + * Returns the type of the input for this test. + */ + Type getInputType() { + exists(int i | + baseInput = SummaryComponentStack::argument(i) and + result = getParameterType(callable, i) + ) + } + + /** + * Returns the Java name for the type of the input to this test. + */ + string getInputTypeString() { result = getShortNameIfPossible(this.getInputType()) } + + /** + * Returns a call to `source()` wrapped in `newWith` methods as needed according to `input`. + * For example, if the input specification is `ArrayElement of MapValue of Argument[0]`, this + * will return `newWithMapValue(newWithArrayElement(source()))`. + */ + string getInput(SummaryComponentStack stack) { + stack = input and result = "source()" + or + exists(SummaryComponentStack s | + result = "newWith" + contentToken(getContent(s.head())) + "(" + this.getInput(s) + ")" and + stack = s.tail() + ) + } + + /** + * Returns `out` wrapped in `get` methods as needed according to `output`. + * For example, if the output specification is `ArrayElement of MapValue of Argument[0]`, this + * will return `getArrayElement(getMapValue(out))`. + */ + string getOutput(SummaryComponentStack componentStack) { + componentStack = output.drop(_) and + ( + if componentStack = baseOutput + then result = "out" + else + result = + "get" + contentToken(getContent(componentStack.head())) + "(" + + this.getOutput(componentStack.tail()) + ")" + ) + } + + /** + * Returns the definition of a `newWith` method needed to set up the input or a `get` method needed to set up the output for this test. + */ + string getASupportMethod() { + result = + "Object newWith" + contentToken(getContent(input.drop(_).head())) + + "(Object element) { return null; }" or + result = + "Object get" + contentToken(getContent(output.drop(_).head())) + + "(Object container) { return null; }" + } + + /** + * Returns a CSV row describing a support method (`newWith` or `get` method) needed to set up the output for this test. + * + * For example, `newWithMapValue` will propagate a value from `Argument[0]` to `MapValue of ReturnValue`, and `getMapValue` + * will do the opposite. + */ + string getASupportMethodModel() { + exists(SummaryComponent c, string contentCsvDescription | + c = input.drop(_).head() and contentCsvDescription = getComponentSpec(c) + | + result = + "generatedtest;Test;false;newWith" + contentToken(getContent(c)) + ";;;Argument[0];" + + contentCsvDescription + " of ReturnValue;value" + ) + or + exists(SummaryComponent c, string contentCsvDescription | + c = output.drop(_).head() and contentCsvDescription = getComponentSpec(c) + | + result = + "generatedtest;Test;false;get" + contentToken(getContent(c)) + ";;;" + contentCsvDescription + + " of Argument[0];ReturnValue;value" + ) + } + + /** + * Gets an outer class name that this test would ideally import (and will, unless it clashes with another + * type of the same name). + */ + Type getADesiredImport() { + result = + getRootSourceDeclaration([ + this.getOutputType(), this.getInputType(), callable.getDeclaringType() + ]) + or + // Will refer to parameter types in disambiguating casts, like `(String)null` + mayBeAmbiguous(callable) and result = getRootSourceDeclaration(callable.getAParamType()) + } + + /** + * Gets a test snippet (test body fragment) testing this `callable` propagates value or taint from + * `input` to `output`, as specified by `row_` (which necessarily equals `row`). + */ + string getATestSnippetForRow(string row_) { + row_ = row and + result = + "\t\t{\n\t\t\t// \"" + row + "\"\n\t\t\t" + getShortNameIfPossible(this.getOutputType()) + + " out = null;\n\t\t\t" + this.getInputTypeString() + " in = (" + this.getInputTypeString() + + ")" + this.getInput(baseInput) + ";\n\t\t\t" + this.getInstancePrefix() + this.makeCall() + + ";\n\t\t\t" + "sink(" + this.getOutput(output) + "); " + this.getExpectation() + "\n\t\t}\n" + } +} diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll new file mode 100644 index 00000000000..c06c4daea17 --- /dev/null +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -0,0 +1,52 @@ +import java +private import semmle.code.java.dataflow.internal.DataFlowUtil +private import semmle.code.java.dataflow.ExternalFlow +private import semmle.code.java.dataflow.FlowSummary +private import semmle.code.java.dataflow.internal.FlowSummaryImpl +private import FlowTestCaseUtils + +/** + * Returns a valid Java token naming the field `fc`. + */ +private string getFieldToken(FieldContent fc) { + result = + fc.getField().getDeclaringType().getSourceDeclaration().getName() + "_" + + fc.getField().getName() +} + +/** + * Returns a valid Java token naming the synthetic field `fc`, + * assuming that the name of that field consists only of characters valid in a Java identifier and `.`. + */ +private string getSyntheticFieldToken(SyntheticFieldContent fc) { + exists(string name, int parts | + name = fc.getField() and + parts = count(name.splitAt(".")) + | + if parts = 1 + then result = name + else result = name.splitAt(".", parts - 2) + "_" + name.splitAt(".", parts - 1) + ) +} + +/** + * Returns a token suitable for incorporation into a Java method name describing content `c`. + */ +string contentToken(Content c) { + c instanceof ArrayContent and result = "ArrayElement" + or + c instanceof CollectionContent and result = "Element" + or + c instanceof MapKeyContent and result = "MapKey" + or + c instanceof MapValueContent and result = "MapValue" + or + result = getFieldToken(c) + or + result = getSyntheticFieldToken(c) +} + +/** + * Returns the `content` wrapped by `component`, if any. + */ +Content getContent(SummaryComponent component) { component = SummaryComponent::content(result) } diff --git a/java/ql/src/utils/FlowTestCaseUtils.qll b/java/ql/src/utils/FlowTestCaseUtils.qll new file mode 100644 index 00000000000..423996df851 --- /dev/null +++ b/java/ql/src/utils/FlowTestCaseUtils.qll @@ -0,0 +1,127 @@ +import java +private import semmle.code.java.dataflow.internal.DataFlowUtil +private import semmle.code.java.dataflow.FlowSummary +private import FlowTestCase + +/** + * Returns `t`'s outermost enclosing type, in raw form (i.e. generic types are given without generic parameters, and type variables are replaced by their bounds). + */ +Type getRootSourceDeclaration(Type t) { + if t instanceof RefType + then result = getRootType(replaceTypeVariable(t)).getSourceDeclaration() + else result = t +} + +/** + * Holds if type `t` does not clash with another type we want to import that has the same base name. + */ +predicate isImportable(Type t) { + t = any(TestCase tc).getADesiredImport() and + t = + unique(Type sharesBaseName | + sharesBaseName = any(TestCase tc).getADesiredImport() and + sharesBaseName.getName() = t.getName() + | + sharesBaseName + ) +} + +/** + * Returns `t`'s first upper bound if `t` is a type variable; otherwise returns `t`. + */ +RefType replaceTypeVariable(RefType t) { + if t instanceof TypeVariable + then result = replaceTypeVariable(t.(TypeVariable).getFirstUpperBoundType()) + else result = t +} + +/** + * Returns a zero value of primitive type `t`. + */ +string getZero(PrimitiveType t) { + t.hasName("float") and result = "0.0f" + or + t.hasName("double") and result = "0.0" + or + t.hasName("int") and result = "0" + or + t.hasName("boolean") and result = "false" + or + t.hasName("short") and result = "(short)0" + or + t.hasName("byte") and result = "(byte)0" + or + t.hasName("char") and result = "'a'" + or + t.hasName("long") and result = "0L" +} + +/** + * Holds if `c` may require disambiguation from an overload with the same argument count. + */ +predicate mayBeAmbiguous(Callable c) { + exists(Callable other, string package, string type, string name | + c.hasQualifiedName(package, type, name) and + other.hasQualifiedName(package, type, name) and + other.getNumberOfParameters() = c.getNumberOfParameters() and + other != c + ) +} + +/** + * Returns the outermost type enclosing type `t` (which may be `t` itself). + */ +RefType getRootType(RefType t) { + if t instanceof NestedType + then result = getRootType(t.(NestedType).getEnclosingType()) + else + if t instanceof Array + then result = getRootType(t.(Array).getElementType()) + else result = t +} + +/** + * Returns a printable name for type `t`, stripped of generics and, if a type variable, + * replaced by its bound. Usually this is a short name, but it may be package-qualified + * if we cannot import it due to a name clash. + */ +string getShortNameIfPossible(Type t) { + if t instanceof Array + then result = getShortNameIfPossible(t.(Array).getComponentType()) + "[]" + else ( + getRootSourceDeclaration(t) = any(TestCase tc).getADesiredImport() and + if t instanceof RefType + then + exists(RefType replaced, string nestedName | + replaced = replaceTypeVariable(t).getSourceDeclaration() and + nestedName = replaced.nestedName().replaceAll("$", ".") + | + if isImportable(getRootSourceDeclaration(t)) + then result = nestedName + else result = replaced.getPackage().getName() + "." + nestedName + ) + else result = t.getName() + ) +} + +/** + * Gets a string that specifies summary component `c` in a summary specification CSV row. + */ +string getComponentSpec(SummaryComponent c) { + exists(Content content | + c = SummaryComponent::content(content) and + ( + content instanceof ArrayContent and result = "ArrayElement" + or + content instanceof MapValueContent and result = "MapValue" + or + content instanceof MapKeyContent and result = "MapKey" + or + content instanceof CollectionContent and result = "Element" + or + result = "Field[" + content.(FieldContent).getField().getQualifiedName() + "]" + or + result = "SyntheticField[" + content.(SyntheticFieldContent).getField() + "]" + ) + ) +} diff --git a/java/ql/src/utils/GenerateFlowTestCase.qll b/java/ql/src/utils/GenerateFlowTestCase.qll index 0f7f0328f46..04978e55d75 100644 --- a/java/ql/src/utils/GenerateFlowTestCase.qll +++ b/java/ql/src/utils/GenerateFlowTestCase.qll @@ -8,25 +8,9 @@ private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.ExternalFlow private import semmle.code.java.dataflow.FlowSummary private import semmle.code.java.dataflow.internal.FlowSummaryImpl - -/** - * A CSV row to generate tests for. Users should extend this to define which - * tests to generate. Rows specified here should also satisfy `SummaryModelCsv.row`. - */ -class TargetSummaryModelCsv extends Unit { - /** - * Holds if a test should be generated for `row`. - */ - abstract predicate row(string r); -} - -/** - * Gets a CSV row for which a test has been requested, but `SummaryModelCsv.row` does not hold of it. - */ -query string missingSummaryModelCsv() { - any(TargetSummaryModelCsv target).row(result) and - not any(SummaryModelCsv model).row(result) -} +import FlowTestCase +private import FlowTestCaseSupportMethods +private import FlowTestCaseUtils /** * Gets a CSV row for which a test has been requested, and `SummaryModelCsv.row` does hold, but @@ -73,471 +57,6 @@ query string noTestCaseGenerated() { not exists(any(TestCase tc).getATestSnippetForRow(result)) } -private class CallableToTest extends Callable { - CallableToTest() { - exists( - string namespace, string type, boolean subtypes, string name, string signature, string ext - | - summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _) and - this = interpretElement(namespace, type, subtypes, name, signature, ext) and - this.isPublic() and - getRootType(this.getDeclaringType()).isPublic() - ) - } -} - -/** - * Returns type of parameter `i` of `callable`, including the type of `this` for parameter -1. - */ -Type getParameterType(CallableToTest callable, int i) { - if i = -1 then result = callable.getDeclaringType() else result = callable.getParameterType(i) -} - -/** - * Returns a zero value of primitive type `t`. - */ -string getZero(PrimitiveType t) { - t.hasName("float") and result = "0.0f" - or - t.hasName("double") and result = "0.0" - or - t.hasName("int") and result = "0" - or - t.hasName("boolean") and result = "false" - or - t.hasName("short") and result = "(short)0" - or - t.hasName("byte") and result = "(byte)0" - or - t.hasName("char") and result = "'a'" - or - t.hasName("long") and result = "0L" -} - -/** - * Holds if `c` may require disambiguation from an overload with the same argument count. - */ -predicate mayBeAmbiguous(Callable c) { - exists(Callable other, string package, string type, string name | - c.hasQualifiedName(package, type, name) and - other.hasQualifiedName(package, type, name) and - other.getNumberOfParameters() = c.getNumberOfParameters() and - other != c - ) -} - -/** - * Returns the `content` wrapped by `component`, if any. - */ -Content getContent(SummaryComponent component) { component = SummaryComponent::content(result) } - -/** - * Returns a valid Java token naming the field `fc`. - */ -string getFieldToken(FieldContent fc) { - result = - fc.getField().getDeclaringType().getSourceDeclaration().getName() + "_" + - fc.getField().getName() -} - -/** - * Returns a valid Java token naming the synthetic field `fc`, - * assuming that the name of that field consists only of characters valid in a Java identifier and `.`. - */ -string getSyntheticFieldToken(SyntheticFieldContent fc) { - exists(string name, int parts | - name = fc.getField() and - parts = count(name.splitAt(".")) - | - if parts = 1 - then result = name - else result = name.splitAt(".", parts - 2) + "_" + name.splitAt(".", parts - 1) - ) -} - -/** - * Returns a token suitable for incorporation into a Java method name describing content `c`. - */ -string contentToken(Content c) { - c instanceof ArrayContent and result = "ArrayElement" - or - c instanceof CollectionContent and result = "Element" - or - c instanceof MapKeyContent and result = "MapKey" - or - c instanceof MapValueContent and result = "MapValue" - or - result = getFieldToken(c) - or - result = getSyntheticFieldToken(c) -} - -/** - * Returns the outermost type enclosing type `t` (which may be `t` itself). - */ -RefType getRootType(RefType t) { - if t instanceof NestedType - then result = getRootType(t.(NestedType).getEnclosingType()) - else - if t instanceof Array - then result = getRootType(t.(Array).getElementType()) - else result = t -} - -/** - * Returns `t`'s first upper bound if `t` is a type variable; otherwise returns `t`. - */ -RefType replaceTypeVariable(RefType t) { - if t instanceof TypeVariable - then result = replaceTypeVariable(t.(TypeVariable).getFirstUpperBoundType()) - else result = t -} - -/** - * Returns `t`'s outermost enclosing type, in raw form (i.e. generic types are given without generic parameters, and type variables are replaced by their bounds). - */ -Type getRootSourceDeclaration(Type t) { - if t instanceof RefType - then result = getRootType(replaceTypeVariable(t)).getSourceDeclaration() - else result = t -} - -/** - * A test snippet (a fragment of Java code that checks that `row` causes `callable` to propagate value/taint (according to `preservesValue`) - * from `input` to `output`). Usually there is one of these per CSV row (`row`), but there may be more if `row` describes more than one - * override or overload of a particular method, or if the input or output specifications cover more than one argument. - */ -private newtype TTestCase = - MkTestCase( - CallableToTest callable, SummaryComponentStack input, SummaryComponentStack output, string kind, - string row - ) { - exists( - string namespace, string type, boolean subtypes, string name, string signature, string ext, - string inputSpec, string outputSpec - | - any(TargetSummaryModelCsv tsmc).row(row) and - summaryModel(namespace, type, subtypes, name, signature, ext, inputSpec, outputSpec, kind, row) and - callable = interpretElement(namespace, type, subtypes, name, signature, ext) and - Private::External::interpretSpec(inputSpec, input) and - Private::External::interpretSpec(outputSpec, output) - ) - } - -/** - * A test snippet (as `TTestCase`, except `baseInput` and `baseOutput` hold the bottom of the summary stacks - * `input` and `output` respectively (hence, `baseInput` and `baseOutput` are parameters or return values). - */ -class TestCase extends TTestCase { - CallableToTest callable; - SummaryComponentStack input; - SummaryComponentStack output; - SummaryComponentStack baseInput; - SummaryComponentStack baseOutput; - string kind; - string row; - - TestCase() { - this = MkTestCase(callable, input, output, kind, row) and - baseInput = input.drop(input.length() - 1) and - baseOutput = output.drop(output.length() - 1) - } - - /** - * Returns a representation of this test case's parameters suitable for debugging. - */ - string toString() { - result = - row + " / " + callable + " / " + input + " / " + output + " / " + baseInput + " / " + - baseOutput + " / " + kind - } - - /** - * Returns a value to pass as `callable`'s `argIdx`th argument whose value is irrelevant to the test - * being generated. This will be a zero or a null value, perhaps typecast if we need to disambiguate overloads. - */ - string getFiller(int argIdx) { - exists(Type t | t = callable.getParameterType(argIdx) | - t instanceof RefType and - ( - if mayBeAmbiguous(callable) - then result = "(" + getShortNameIfPossible(t) + ")null" - else result = "null" - ) - or - result = getZero(t) - ) - } - - /** - * Returns the value to pass for `callable`'s `i`th argument, which may be `in` if this is the input argument for - * this test, `out` if it is the output, `instance` if this is an instance method and the instance is neither the - * input nor the output, or a zero/null filler value otherwise. - */ - string getArgument(int i) { - (i = -1 or exists(callable.getParameter(i))) and - if baseInput = SummaryComponentStack::argument(i) - then result = "in" - else - if baseOutput = SummaryComponentStack::argument(i) - then result = "out" - else - if i = -1 - then result = "instance" - else result = this.getFiller(i) - } - - /** - * Returns a statement invoking `callable`, passing `input` and capturing `output` as needed. - */ - string makeCall() { - // For example, one of: - // out = in.method(filler); - // or - // out = filler.method(filler, in, filler); - // or - // out = Type.method(filler, in, filler); - // or - // filler.method(filler, in, out, filler); - // or - // Type.method(filler, in, out, filler); - // or - // out = new Type(filler, in, filler); - // or - // new Type(filler, in, out, filler); - // or - // in.method(filler, out, filler); - // or - // out.method(filler, in, filler); - exists(string storePrefix, string invokePrefix, string args | - ( - if - baseOutput = SummaryComponentStack::return() - or - callable instanceof Constructor and baseOutput = SummaryComponentStack::argument(-1) - then storePrefix = "out = " - else storePrefix = "" - ) and - ( - if callable instanceof Constructor - then invokePrefix = "new " - else - if callable.(Method).isStatic() - then invokePrefix = getShortNameIfPossible(callable.getDeclaringType()) + "." - else invokePrefix = this.getArgument(-1) + "." - ) and - args = concat(int i | i >= 0 | this.getArgument(i), ", " order by i) and - result = storePrefix + invokePrefix + callable.getName() + "(" + args + ")" - ) - } - - /** - * Returns an inline test expectation appropriate to this CSV row. - */ - string getExpectation() { - kind = "value" and result = "// $ hasValueFlow" - or - kind = "taint" and result = "// $ hasTaintFlow" - } - - /** - * Returns a declaration and initialisation of a variable named `instance` if required; otherwise returns an empty string. - */ - string getInstancePrefix() { - if - callable instanceof Method and - not callable.(Method).isStatic() and - baseOutput != SummaryComponentStack::argument(-1) and - baseInput != SummaryComponentStack::argument(-1) - then - // In this case `out` is the instance. - result = getShortNameIfPossible(callable.getDeclaringType()) + " instance = null;\n\t\t\t" - else result = "" - } - - /** - * Returns the type of the output for this test. - */ - Type getOutputType() { - if baseOutput = SummaryComponentStack::return() - then result = callable.getReturnType() - else - exists(int i | - baseOutput = SummaryComponentStack::argument(i) and - result = getParameterType(callable, i) - ) - } - - /** - * Returns the type of the input for this test. - */ - Type getInputType() { - exists(int i | - baseInput = SummaryComponentStack::argument(i) and - result = getParameterType(callable, i) - ) - } - - /** - * Returns the Java name for the type of the input to this test. - */ - string getInputTypeString() { result = getShortNameIfPossible(this.getInputType()) } - - /** - * Returns a call to `source()` wrapped in `newWith` methods as needed according to `input`. - * For example, if the input specification is `ArrayElement of MapValue of Argument[0]`, this - * will return `newWithMapValue(newWithArrayElement(source()))`. - */ - string getInput(SummaryComponentStack stack) { - stack = input and result = "source()" - or - exists(SummaryComponentStack s | - result = "newWith" + contentToken(getContent(s.head())) + "(" + this.getInput(s) + ")" and - stack = s.tail() - ) - } - - /** - * Returns `out` wrapped in `get` methods as needed according to `output`. - * For example, if the output specification is `ArrayElement of MapValue of Argument[0]`, this - * will return `getArrayElement(getMapValue(out))`. - */ - string getOutput(SummaryComponentStack componentStack) { - componentStack = output.drop(_) and - ( - if componentStack = baseOutput - then result = "out" - else - result = - "get" + contentToken(getContent(componentStack.head())) + "(" + - this.getOutput(componentStack.tail()) + ")" - ) - } - - /** - * Returns the definition of a `newWith` method needed to set up the input or a `get` method needed to set up the output for this test. - */ - string getASupportMethod() { - result = - "Object newWith" + contentToken(getContent(input.drop(_).head())) + - "(Object element) { return null; }" or - result = - "Object get" + contentToken(getContent(output.drop(_).head())) + - "(Object container) { return null; }" - } - - /** - * Gets a string that specifies summary component `c` in a summary specification CSV row. - */ - string getComponentSpec(SummaryComponent c) { - exists(Content content | - c = SummaryComponent::content(content) and - ( - content instanceof ArrayContent and result = "ArrayElement" - or - content instanceof MapValueContent and result = "MapValue" - or - content instanceof MapKeyContent and result = "MapKey" - or - content instanceof CollectionContent and result = "Element" - or - result = "Field[" + content.(FieldContent).getField().getQualifiedName() + "]" - or - result = "SyntheticField[" + content.(SyntheticFieldContent).getField() + "]" - ) - ) - } - - /** - * Returns a CSV row describing a support method (`newWith` or `get` method) needed to set up the output for this test. - * - * For example, `newWithMapValue` will propagate a value from `Argument[0]` to `MapValue of ReturnValue`, and `getMapValue` - * will do the opposite. - */ - string getASupportMethodModel() { - exists(SummaryComponent c, string contentCsvDescription | - c = input.drop(_).head() and contentCsvDescription = getComponentSpec(c) - | - result = - "generatedtest;Test;false;newWith" + contentToken(getContent(c)) + ";;;Argument[0];" + - contentCsvDescription + " of ReturnValue;value" - ) - or - exists(SummaryComponent c, string contentCsvDescription | - c = output.drop(_).head() and contentCsvDescription = getComponentSpec(c) - | - result = - "generatedtest;Test;false;get" + contentToken(getContent(c)) + ";;;" + contentCsvDescription - + " of Argument[0];ReturnValue;value" - ) - } - - /** - * Gets an outer class name that this test would ideally import (and will, unless it clashes with another - * type of the same name). - */ - Type getADesiredImport() { - result = - getRootSourceDeclaration([ - this.getOutputType(), this.getInputType(), callable.getDeclaringType() - ]) - or - // Will refer to parameter types in disambiguating casts, like `(String)null` - mayBeAmbiguous(callable) and result = getRootSourceDeclaration(callable.getAParamType()) - } - - /** - * Gets a test snippet (test body fragment) testing this `callable` propagates value or taint from - * `input` to `output`, as specified by `row_` (which necessarily equals `row`). - */ - string getATestSnippetForRow(string row_) { - row_ = row and - result = - "\t\t{\n\t\t\t// \"" + row + "\"\n\t\t\t" + getShortNameIfPossible(this.getOutputType()) + - " out = null;\n\t\t\t" + this.getInputTypeString() + " in = (" + this.getInputTypeString() + - ")" + this.getInput(baseInput) + ";\n\t\t\t" + this.getInstancePrefix() + this.makeCall() + - ";\n\t\t\t" + "sink(" + this.getOutput(output) + "); " + this.getExpectation() + "\n\t\t}\n" - } -} - -/** - * Holds if type `t` does not clash with another type we want to import that has the same base name. - */ -predicate isImportable(Type t) { - t = any(TestCase tc).getADesiredImport() and - t = - unique(Type sharesBaseName | - sharesBaseName = any(TestCase tc).getADesiredImport() and - sharesBaseName.getName() = t.getName() - | - sharesBaseName - ) -} - -/** - * Returns a printable name for type `t`, stripped of generics and, if a type variable, - * replaced by its bound. Usually this is a short name, but it may be package-qualified - * if we cannot import it due to a name clash. - */ -string getShortNameIfPossible(Type t) { - if t instanceof Array - then result = getShortNameIfPossible(t.(Array).getComponentType()) + "[]" - else ( - getRootSourceDeclaration(t) = any(TestCase tc).getADesiredImport() and - if t instanceof RefType - then - exists(RefType replaced, string nestedName | - replaced = replaceTypeVariable(t).getSourceDeclaration() and - nestedName = replaced.nestedName().replaceAll("$", ".") - | - if isImportable(getRootSourceDeclaration(t)) - then result = nestedName - else result = replaced.getPackage().getName() + "." + nestedName - ) - else result = t.getName() - ) -} - /** * Returns an import statement to include in the test case header. */ From 2b0f6a272385b3480d756df77d936c9fd6c7087a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Aug 2021 15:07:00 +0100 Subject: [PATCH 365/429] Java: Generate more realistic tests --- java/ql/src/utils/FlowTestCase.qll | 50 +-- .../src/utils/FlowTestCaseSupportMethods.qll | 304 +++++++++++++++++- java/ql/src/utils/GenerateFlowTestCase.py | 2 +- java/ql/src/utils/GenerateFlowTestCase.qll | 11 +- 4 files changed, 323 insertions(+), 44 deletions(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 2ae19a804e9..9ef1b109476 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -234,9 +234,13 @@ class TestCase extends TTestCase { string getInput(SummaryComponentStack stack) { stack = input and result = "source()" or - exists(SummaryComponentStack s | - result = "newWith" + contentToken(getContent(s.head())) + "(" + this.getInput(s) + ")" and - stack = s.tail() + exists(SummaryComponentStack s | s.tail() = stack | + // we currently only know the type if the stack is one level in + s = input and + result = SupportMethod::genMethodFor(this.getInputType(), s).getCall(this.getInput(s)) + or + not s = input and + result = SupportMethod::genMethodForContent(s).getCall(this.getInput(s)) ) } @@ -252,45 +256,19 @@ class TestCase extends TTestCase { then result = "out" else result = - "get" + contentToken(getContent(componentStack.head())) + "(" + - this.getOutput(componentStack.tail()) + ")" + SupportMethod::getMethodForContent(componentStack) + .getCall(this.getOutput(componentStack.tail())) ) } /** * Returns the definition of a `newWith` method needed to set up the input or a `get` method needed to set up the output for this test. */ - string getASupportMethod() { - result = - "Object newWith" + contentToken(getContent(input.drop(_).head())) + - "(Object element) { return null; }" or - result = - "Object get" + contentToken(getContent(output.drop(_).head())) + - "(Object container) { return null; }" - } - - /** - * Returns a CSV row describing a support method (`newWith` or `get` method) needed to set up the output for this test. - * - * For example, `newWithMapValue` will propagate a value from `Argument[0]` to `MapValue of ReturnValue`, and `getMapValue` - * will do the opposite. - */ - string getASupportMethodModel() { - exists(SummaryComponent c, string contentCsvDescription | - c = input.drop(_).head() and contentCsvDescription = getComponentSpec(c) - | - result = - "generatedtest;Test;false;newWith" + contentToken(getContent(c)) + ";;;Argument[0];" + - contentCsvDescription + " of ReturnValue;value" - ) - or - exists(SummaryComponent c, string contentCsvDescription | - c = output.drop(_).head() and contentCsvDescription = getComponentSpec(c) - | - result = - "generatedtest;Test;false;get" + contentToken(getContent(c)) + ";;;" + contentCsvDescription - + " of Argument[0];ReturnValue;value" - ) + SupportMethod getASupportMethod() { + result = SupportMethod::genMethodFor(this.getInputType(), input) or + result = SupportMethod::genMethodForContent(input.tail().drop(_)) or + result = SupportMethod::getMethodFor(this.getOutputType(), output) or + result = SupportMethod::getMethodForContent(output.tail().drop(_)) } /** diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index c06c4daea17..30473b34149 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -32,7 +32,7 @@ private string getSyntheticFieldToken(SyntheticFieldContent fc) { /** * Returns a token suitable for incorporation into a Java method name describing content `c`. */ -string contentToken(Content c) { +private string contentToken(Content c) { c instanceof ArrayContent and result = "ArrayElement" or c instanceof CollectionContent and result = "Element" @@ -49,4 +49,304 @@ string contentToken(Content c) { /** * Returns the `content` wrapped by `component`, if any. */ -Content getContent(SummaryComponent component) { component = SummaryComponent::content(result) } +private Content getContent(SummaryComponent component) { + component = SummaryComponent::content(result) +} + +module SupportMethod { + GenMethod genMethodForContent(SummaryComponentStack c) { + result = min(GenMethod g | g.appliesTo(any(VoidType v), getContent(c.head()))) + } + + GenMethod genMethodFor(Type t, SummaryComponentStack c) { + result = min(GenMethod g | g.appliesTo(t, getContent(c.head()))) + } + + GetMethod getMethodForContent(SummaryComponentStack c) { + result = min(GetMethod g | g.appliesTo(any(VoidType v), getContent(c.head()))) + } + + GetMethod getMethodFor(Type t, SummaryComponentStack c) { + result = min(GetMethod g | g.appliesTo(t, getContent(c.head()))) + } +} + +bindingset[this] +abstract class SupportMethod extends string { + abstract predicate appliesTo(Type t, Content c); + + string getARequiredImport() { none() } + + string getDefinition() { none() } + + bindingset[this, arg] + abstract string getCall(string arg); + + /** + * Gets the CSV row describing this support method if it is needed to set up the output for this test. + * + * For example, `newWithMapValue` will propagate a value from `Argument[0]` to `MapValue of ReturnValue`, and `getMapValue` + * will do the opposite. + */ + string getCsvModel() { none() } +} + +class SourceMethod extends SupportMethod { + SourceMethod() { this = "source" } + + override predicate appliesTo(Type t, Content c) { none() } + + bindingset[arg] + override string getCall(string arg) { + result = "source()" and + // suppress unused variable warning + arg = arg + } + + override string getDefinition() { result = "Object source() { return null; }" } +} + +class SinkMethod extends SupportMethod { + SinkMethod() { this = "sink" } + + override predicate appliesTo(Type t, Content c) { none() } + + bindingset[arg] + override string getCall(string arg) { result = "sink(" + arg + ")" } + + override string getDefinition() { result = "void sink(Object o) { }" } +} + +bindingset[this] +abstract class GetMethod extends SupportMethod { } + +private class DefaultGetMethod extends GetMethod { + Content c; + + // prefix with zzz so the default getter is always last + DefaultGetMethod() { this = "zzzDefaultGet" + contentToken(c) } + + string getName() { result = "get" + contentToken(c) } + + override predicate appliesTo(Type t, Content c1) { + c = c1 and + // suppress unused variable warning + t = t + } + + bindingset[arg] + override string getCall(string arg) { result = this.getName() + "(" + arg + ")" } + + override string getDefinition() { + result = "Object get" + contentToken(c) + "(Object container) { return null; }" + } + + override string getCsvModel() { + result = + "generatedtest;Test;false;" + this.getName() + ";;;" + + getComponentSpec(SummaryComponent::content(c)) + " of Argument[0];ReturnValue;value" + } +} + +private class ListGetMethod extends GetMethod { + ListGetMethod() { this = "listgetmethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getASourceSupertype*().hasQualifiedName("java.lang", "Iterable") and + c instanceof CollectionContent + } + + override string getDefinition() { + result = " T getElement(Iterable it) { return it.iterator().next(); }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getElement(" + arg + ")" } +} + +private class IteratorGetMethod extends GetMethod { + IteratorGetMethod() { this = "iteratorgetmethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getASourceSupertype*().hasQualifiedName("java.util", "Iterator") and + c instanceof CollectionContent + } + + override string getDefinition() { + result = " T getElement(Iterator it) { return it.next(); }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getElement(" + arg + ")" } +} + +private class OptionalGetMethod extends GetMethod { + OptionalGetMethod() { this = "optionalgetmethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getSourceDeclaration().hasQualifiedName("java.util", "Optional") and + c instanceof CollectionContent + } + + override string getDefinition() { result = " T getElement(Optional o) { return o.get(); }" } + + bindingset[arg] + override string getCall(string arg) { result = "getElement(" + arg + ")" } +} + +private class MapGetKeyMethod extends GetMethod { + MapGetKeyMethod() { this = "mapgetkeymethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getASourceSupertype*().hasQualifiedName("java.util", "Map") and + c instanceof MapKeyContent + } + + override string getDefinition() { + result = " K getMapKey(Map map) { return map.keySet().iterator().next(); }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getMapKey(" + arg + ")" } +} + +private class MapValueGetMethod extends GetMethod { + MapValueGetMethod() { this = "MapValueGetMethod" } + + override predicate appliesTo(Type t, Content c) { + t.(RefType).getASourceSupertype*().hasQualifiedName("java.util", "Map") and + c instanceof MapValueContent + } + + override string getDefinition() { + result = " V getMapValue(Map map) { return map.get(null); }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getMapValue(" + arg + ")" } +} + +private class ArrayGetMethod extends GetMethod { + ArrayGetMethod() { this = "arraygetmethod" } + + override predicate appliesTo(Type t, Content c) { + t instanceof Array and + c instanceof ArrayContent + } + + override string getDefinition() { + result = " T getArrayElement(T[] array) { return array[0]; }" + } + + bindingset[arg] + override string getCall(string arg) { result = "getArrayElement(" + arg + ")" } +} + +bindingset[this] +abstract class GenMethod extends SupportMethod { } + +private class DefaultGenMethod extends GenMethod { + Content c; + + // prefix with zzz so the default generator is always last + DefaultGenMethod() { this = "zzzDefaultGen" + contentToken(c) } + + string getName() { result = "newWith" + contentToken(c) } + + override predicate appliesTo(Type t, Content c1) { + c = c1 and + // suppress unused variable warning + t = t + } + + bindingset[arg] + override string getCall(string arg) { result = this.getName() + "(" + arg + ")" } + + override string getDefinition() { + result = "Object newWith" + contentToken(c) + "(Object element) { return null; }" + } + + override string getCsvModel() { + result = + "generatedtest;Test;false;" + this.getName() + ";;;Argument[0];" + + getComponentSpec(SummaryComponent::content(c)) + " of ReturnValue;value" + } +} + +private class ListGenMethod extends GenMethod { + ListGenMethod() { this = "listgenmethod" } + + override predicate appliesTo(Type t, Content c) { + exists(GenericType list | list.hasQualifiedName("java.util", "List") | + t = list or list.getAParameterizedType().getASupertype*() = t + ) and + c instanceof CollectionContent + } + + bindingset[arg] + override string getCall(string arg) { result = "List.of(" + arg + ")" } +} + +private class OptionalGenMethod extends GenMethod { + OptionalGenMethod() { this = "optionalgenmethod" } + + override predicate appliesTo(Type t, Content c) { + exists(GenericType list | list.hasQualifiedName("java.util", "List") | + list.getAParameterizedType().getASupertype*() = t + ) and + c instanceof CollectionContent + } + + bindingset[arg] + override string getCall(string arg) { result = "Optional.of(" + arg + ")" } +} + +private class MapGenKeyMethod extends GenMethod { + MapGenKeyMethod() { this = "mapkeygenmethod" } + + override predicate appliesTo(Type t, Content c) { + exists(GenericType map | map.hasQualifiedName("java.util", "Map") | + map.getAParameterizedType().getASupertype*() = t + ) and + c instanceof MapKeyContent + } + + bindingset[arg] + override string getCall(string arg) { result = "Map.of(" + arg + ", null)" } +} + +private class MapGenValueMethod extends GenMethod { + MapGenValueMethod() { this = "mapvaluegenmethod" } + + override predicate appliesTo(Type t, Content c) { + exists(GenericType map | map.hasQualifiedName("java.util", "Map") | + map.getAParameterizedType().getASupertype*() = t + ) and + c instanceof MapValueContent + } + + bindingset[arg] + override string getCall(string arg) { result = "Map.of(null, " + arg + ")" } +} + +string getConvertExprIfNotObject(RefType t) { + if t.hasQualifiedName("java.lang", "Object") + then result = "" + else result = "(" + getShortNameIfPossible(t) + ")" +} + +private class ArrayGenMethod extends GenMethod { + Array type; + + ArrayGenMethod() { this = type.getName() + "genmethod" } + + override predicate appliesTo(Type t, Content c) { + t = type and + c instanceof ArrayContent + } + + bindingset[arg] + override string getCall(string arg) { + result = "{" + getConvertExprIfNotObject(type.getElementType()) + arg + "}" + } +} diff --git a/java/ql/src/utils/GenerateFlowTestCase.py b/java/ql/src/utils/GenerateFlowTestCase.py index 15bdfc2eb87..757a94fe92d 100755 --- a/java/ql/src/utils/GenerateFlowTestCase.py +++ b/java/ql/src/utils/GenerateFlowTestCase.py @@ -127,7 +127,7 @@ queryDir = os.path.join(workDir, "query") os.makedirs(queryDir) qlFile = os.path.join(queryDir, "gen.ql") with open(os.path.join(queryDir, "qlpack.yml"), "w") as f: - f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql/java-queries") + f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql-java") with open(qlFile, "w") as f: f.write( "import java\nimport utils.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") diff --git a/java/ql/src/utils/GenerateFlowTestCase.qll b/java/ql/src/utils/GenerateFlowTestCase.qll index 04978e55d75..ddd18d6d25a 100644 --- a/java/ql/src/utils/GenerateFlowTestCase.qll +++ b/java/ql/src/utils/GenerateFlowTestCase.qll @@ -73,16 +73,16 @@ string getAnImportStatement() { /** * Returns a support method to include in the generated test class. */ -string getASupportMethod() { - result = "Object source() { return null; }" or - result = "void sink(Object o) { }" or +SupportMethod getASupportMethod() { + result instanceof SourceMethod or + result instanceof SinkMethod or result = any(TestCase tc).getASupportMethod() } /** * Returns a CSV specification of the taint-/value-propagation behaviour of a test support method (`get` or `newWith` method). */ -query string getASupportMethodModel() { result = any(TestCase tc).getASupportMethodModel() } +query string getASupportMethodModel() { result = getASupportMethod().getCsvModel() } /** * Gets a Java file body testing all requested CSV rows against whatever classes and methods they resolve against. @@ -91,7 +91,8 @@ query string getTestCase() { result = "package generatedtest;\n\n" + concat(getAnImportStatement() + "\n") + "\n// Test case generated by GenerateFlowTestCase.ql\npublic class Test {\n\n" + - concat("\t" + getASupportMethod() + "\n") + "\n\tpublic void test() throws Exception {\n\n" + + concat("\t" + getASupportMethod().getDefinition() + "\n") + + "\n\tpublic void test() throws Exception {\n\n" + concat(string row, string snippet | snippet = any(TestCase tc).getATestSnippetForRow(row) | From 73d6177477a98c96443204c4bd5f45e9b5393ed7 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 12:56:47 -0700 Subject: [PATCH 366/429] Java test gen: make char zero '\0' --- java/ql/src/utils/FlowTestCaseUtils.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/FlowTestCaseUtils.qll b/java/ql/src/utils/FlowTestCaseUtils.qll index 423996df851..a8e3beb183c 100644 --- a/java/ql/src/utils/FlowTestCaseUtils.qll +++ b/java/ql/src/utils/FlowTestCaseUtils.qll @@ -51,7 +51,7 @@ string getZero(PrimitiveType t) { or t.hasName("byte") and result = "(byte)0" or - t.hasName("char") and result = "'a'" + t.hasName("char") and result = "'\\0'" or t.hasName("long") and result = "0L" } From 1bd5eb5120602431ae23e43bd8ec854b398d66cc Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 13:49:03 -0700 Subject: [PATCH 367/429] Use if statement instead of manual disjuction --- java/ql/src/utils/FlowTestCase.qll | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 9ef1b109476..9afc1fe6627 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -236,11 +236,9 @@ class TestCase extends TTestCase { or exists(SummaryComponentStack s | s.tail() = stack | // we currently only know the type if the stack is one level in - s = input and - result = SupportMethod::genMethodFor(this.getInputType(), s).getCall(this.getInput(s)) - or - not s = input and - result = SupportMethod::genMethodForContent(s).getCall(this.getInput(s)) + if s = input + then result = SupportMethod::genMethodFor(this.getInputType(), s).getCall(this.getInput(s)) + else result = SupportMethod::genMethodForContent(s).getCall(this.getInput(s)) ) } From ce8d14e6efa2bedf66e83b46dd510602436b7813 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 13:52:38 -0700 Subject: [PATCH 368/429] Add a priority predicate for test generation support methods --- .../src/utils/FlowTestCaseSupportMethods.qll | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 30473b34149..99c51e03d76 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -55,19 +55,25 @@ private Content getContent(SummaryComponent component) { module SupportMethod { GenMethod genMethodForContent(SummaryComponentStack c) { - result = min(GenMethod g | g.appliesTo(any(VoidType v), getContent(c.head()))) + result = genMethodFor(any(VoidType v), c) } GenMethod genMethodFor(Type t, SummaryComponentStack c) { - result = min(GenMethod g | g.appliesTo(t, getContent(c.head()))) + result = + min(GenMethod g | + g = min(GenMethod g1 | g1.appliesTo(t, getContent(c.head())) | g1 order by g1.getPriority()) + ) } GetMethod getMethodForContent(SummaryComponentStack c) { - result = min(GetMethod g | g.appliesTo(any(VoidType v), getContent(c.head()))) + result = getMethodFor(any(VoidType v), c) } GetMethod getMethodFor(Type t, SummaryComponentStack c) { - result = min(GetMethod g | g.appliesTo(t, getContent(c.head()))) + result = + min(GetMethod g | + g = min(GetMethod g1 | g1.appliesTo(t, getContent(c.head())) | g1 order by g1.getPriority()) + ) } } @@ -82,6 +88,10 @@ abstract class SupportMethod extends string { bindingset[this, arg] abstract string getCall(string arg); + /** Gets the priority of this support method. Lower priorities are preferred when multiple support methods apply. */ + bindingset[this] + int getPriority() { result = 50 } + /** * Gets the CSV row describing this support method if it is needed to set up the output for this test. * @@ -123,11 +133,12 @@ abstract class GetMethod extends SupportMethod { } private class DefaultGetMethod extends GetMethod { Content c; - // prefix with zzz so the default getter is always last - DefaultGetMethod() { this = "zzzDefaultGet" + contentToken(c) } + DefaultGetMethod() { this = "DefaultGet" + contentToken(c) } string getName() { result = "get" + contentToken(c) } + override int getPriority() { result = 999 } + override predicate appliesTo(Type t, Content c1) { c = c1 and // suppress unused variable warning @@ -248,11 +259,12 @@ abstract class GenMethod extends SupportMethod { } private class DefaultGenMethod extends GenMethod { Content c; - // prefix with zzz so the default generator is always last - DefaultGenMethod() { this = "zzzDefaultGen" + contentToken(c) } + DefaultGenMethod() { this = "DefaultGen" + contentToken(c) } string getName() { result = "newWith" + contentToken(c) } + override int getPriority() { result = 999 } + override predicate appliesTo(Type t, Content c1) { c = c1 and // suppress unused variable warning From e7611ab641c1a39a0c81704859cc4adbb99d295b Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 13:55:18 -0700 Subject: [PATCH 369/429] Move getCall and appliesTo to relevant classes --- .../src/utils/FlowTestCaseSupportMethods.qll | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 99c51e03d76..6e95b900b09 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -79,15 +79,10 @@ module SupportMethod { bindingset[this] abstract class SupportMethod extends string { - abstract predicate appliesTo(Type t, Content c); - string getARequiredImport() { none() } string getDefinition() { none() } - bindingset[this, arg] - abstract string getCall(string arg); - /** Gets the priority of this support method. Lower priorities are preferred when multiple support methods apply. */ bindingset[this] int getPriority() { result = 50 } @@ -104,31 +99,28 @@ abstract class SupportMethod extends string { class SourceMethod extends SupportMethod { SourceMethod() { this = "source" } - override predicate appliesTo(Type t, Content c) { none() } - - bindingset[arg] - override string getCall(string arg) { - result = "source()" and - // suppress unused variable warning - arg = arg - } - override string getDefinition() { result = "Object source() { return null; }" } } class SinkMethod extends SupportMethod { SinkMethod() { this = "sink" } - override predicate appliesTo(Type t, Content c) { none() } - - bindingset[arg] - override string getCall(string arg) { result = "sink(" + arg + ")" } - override string getDefinition() { result = "void sink(Object o) { }" } } bindingset[this] -abstract class GetMethod extends SupportMethod { } +abstract class GetMethod extends SupportMethod { + /** + * Holds if this get method can be used to get the content `c` from the type `t`. + */ + abstract predicate appliesTo(Type t, Content c); + + /** + * Gets the call to get the content from the argument `arg`. + */ + bindingset[this, arg] + abstract string getCall(string arg); +} private class DefaultGetMethod extends GetMethod { Content c; @@ -254,7 +246,18 @@ private class ArrayGetMethod extends GetMethod { } bindingset[this] -abstract class GenMethod extends SupportMethod { } +abstract class GenMethod extends SupportMethod { + /** + * Holds if this generator method can be used to generate a new `t` that contains content `c`. + */ + abstract predicate appliesTo(Type t, Content c); + + /** + * Gets the call to generate an object with content `arg`. + */ + bindingset[this, arg] + abstract string getCall(string arg); +} private class DefaultGenMethod extends GenMethod { Content c; From abf3bbbe8d89b9d5494afe784a5ae80018dd0085 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 13:57:04 -0700 Subject: [PATCH 370/429] Add qldoc for public elements --- java/ql/src/utils/FlowTestCase.qll | 4 +++ .../src/utils/FlowTestCaseSupportMethods.qll | 26 +++++++++++++++++++ java/ql/src/utils/FlowTestCaseUtils.qll | 4 +++ 3 files changed, 34 insertions(+) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 9afc1fe6627..6d1b3dbc4f6 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -1,3 +1,7 @@ +/** + * Classes pertaining to test cases themselves. + */ + import java private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.ExternalFlow diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 6e95b900b09..19ccf7b7668 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -1,3 +1,7 @@ +/** + * Contains predicates and classes relating to support methods for tests, such as the `source()` and `sink()`. + */ + import java private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.ExternalFlow @@ -53,11 +57,14 @@ private Content getContent(SummaryComponent component) { component = SummaryComponent::content(result) } +/** Contains utility predicates for getting relevant support methods. */ module SupportMethod { + /** Gets a generator method for the content type of the head of the component stack `c`. */ GenMethod genMethodForContent(SummaryComponentStack c) { result = genMethodFor(any(VoidType v), c) } + /** Gets a generator method for the type `t` and the content type of the head of the component stack `c`. */ GenMethod genMethodFor(Type t, SummaryComponentStack c) { result = min(GenMethod g | @@ -65,10 +72,12 @@ module SupportMethod { ) } + /** Gets a getter method for the content type of the head of the component stack `c`. */ GetMethod getMethodForContent(SummaryComponentStack c) { result = getMethodFor(any(VoidType v), c) } + /** Gets a getter method for the type `t` and the content type of the head of the component stack `c`. */ GetMethod getMethodFor(Type t, SummaryComponentStack c) { result = min(GetMethod g | @@ -77,10 +86,15 @@ module SupportMethod { } } +/** + * A support method for tests, such as `source()` or `sink()`. + */ bindingset[this] abstract class SupportMethod extends string { + /** Gets an import that is required for this support method. */ string getARequiredImport() { none() } + /** Gets the Java definition of this support method, if one is necessary. */ string getDefinition() { none() } /** Gets the priority of this support method. Lower priorities are preferred when multiple support methods apply. */ @@ -96,18 +110,27 @@ abstract class SupportMethod extends string { string getCsvModel() { none() } } +/** + * The method `source()` which is considered as the source for the flow test. + */ class SourceMethod extends SupportMethod { SourceMethod() { this = "source" } override string getDefinition() { result = "Object source() { return null; }" } } +/** + * The method `sink()` which is considered as the sink for the flow test. + */ class SinkMethod extends SupportMethod { SinkMethod() { this = "sink" } override string getDefinition() { result = "void sink(Object o) { }" } } +/** + * A method for getting content from a type. + */ bindingset[this] abstract class GetMethod extends SupportMethod { /** @@ -245,6 +268,9 @@ private class ArrayGetMethod extends GetMethod { override string getCall(string arg) { result = "getArrayElement(" + arg + ")" } } +/** + * A method for generating a type with content. + */ bindingset[this] abstract class GenMethod extends SupportMethod { /** diff --git a/java/ql/src/utils/FlowTestCaseUtils.qll b/java/ql/src/utils/FlowTestCaseUtils.qll index a8e3beb183c..7c76a09d238 100644 --- a/java/ql/src/utils/FlowTestCaseUtils.qll +++ b/java/ql/src/utils/FlowTestCaseUtils.qll @@ -1,3 +1,7 @@ +/** + * Utility predicates useful for test generation. + */ + import java private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.FlowSummary From 2132ee52d5d82acb7029db62fda9721972a3f5eb Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 13:57:16 -0700 Subject: [PATCH 371/429] Restrict the size of appliesTo for default methods --- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 19ccf7b7668..831c394a188 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -8,6 +8,7 @@ private import semmle.code.java.dataflow.ExternalFlow private import semmle.code.java.dataflow.FlowSummary private import semmle.code.java.dataflow.internal.FlowSummaryImpl private import FlowTestCaseUtils +private import FlowTestCase /** * Returns a valid Java token naming the field `fc`. @@ -157,7 +158,7 @@ private class DefaultGetMethod extends GetMethod { override predicate appliesTo(Type t, Content c1) { c = c1 and // suppress unused variable warning - t = t + t = [any(TestCase tc).getOutputType(), any(VoidType v)] } bindingset[arg] @@ -297,7 +298,7 @@ private class DefaultGenMethod extends GenMethod { override predicate appliesTo(Type t, Content c1) { c = c1 and // suppress unused variable warning - t = t + t = [any(TestCase tc).getInputType(), any(VoidType v)] } bindingset[arg] From ede2ae11e905499752887bc0c24202f0af7fbb18 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Fri, 27 Aug 2021 14:17:48 -0400 Subject: [PATCH 372/429] Fix incompatibility with release CLI This fixes #6563, in which a customer reports being unable to run a query suite despite following the "Getting Started with the CodeQL CLI" instructions. The problem is that the released versions of the CodeQL CLI incorrectly disallow any reference to a library pack from within a .qls file. This is a CLI bug that will be fixed in the next CLI release, but since our policy is to make `github/codeql`'s `main` branch compatible with the latest released CLI, we need to work around this for now by pretending `codeql/suite-helpers` is a query pack. --- misc/suite-helpers/qlpack.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index ca0a6732f5a..3ac4457ebe5 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,3 +1,2 @@ name: codeql/suite-helpers version: 0.0.2 -library: true From 0d174f2dafc3c1f3711911117dc7c126bb1ed585 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 16:13:55 -0700 Subject: [PATCH 373/429] Only include support methods and imports from working test cases --- java/ql/src/utils/GenerateFlowTestCase.qll | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/java/ql/src/utils/GenerateFlowTestCase.qll b/java/ql/src/utils/GenerateFlowTestCase.qll index ddd18d6d25a..405f2794a61 100644 --- a/java/ql/src/utils/GenerateFlowTestCase.qll +++ b/java/ql/src/utils/GenerateFlowTestCase.qll @@ -57,12 +57,17 @@ query string noTestCaseGenerated() { not exists(any(TestCase tc).getATestSnippetForRow(result)) } +/** + * Gets a valid test case, i.e. one that has a test snippet. + */ +TestCase getAValidTestCase() { exists(result.getATestSnippetForRow(_)) } + /** * Returns an import statement to include in the test case header. */ string getAnImportStatement() { exists(RefType t | - t = any(TestCase tc).getADesiredImport() and + t = getAValidTestCase().getADesiredImport() and isImportable(t) and t.getPackage().getName() != "java.lang" | @@ -76,7 +81,7 @@ string getAnImportStatement() { SupportMethod getASupportMethod() { result instanceof SourceMethod or result instanceof SinkMethod or - result = any(TestCase tc).getASupportMethod() + result = getAValidTestCase().getASupportMethod() } /** From 9d66761eeb3e07c0e28075a3916424d2e2227710 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 16:34:08 -0700 Subject: [PATCH 374/429] Consider a callable to ambiguous if it has a varargs parameter --- java/ql/src/utils/FlowTestCaseUtils.qll | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/ql/src/utils/FlowTestCaseUtils.qll b/java/ql/src/utils/FlowTestCaseUtils.qll index 7c76a09d238..3456678bd16 100644 --- a/java/ql/src/utils/FlowTestCaseUtils.qll +++ b/java/ql/src/utils/FlowTestCaseUtils.qll @@ -70,6 +70,8 @@ predicate mayBeAmbiguous(Callable c) { other.getNumberOfParameters() = c.getNumberOfParameters() and other != c ) + or + c.isVarargs() } /** From 119de6c60cef94beb45e3b6d5564fead0d9f8b25 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 17:15:37 -0700 Subject: [PATCH 375/429] Replace type variables before attempting to match to an array generation --- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 831c394a188..ea7c6c4d7c7 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -383,7 +383,7 @@ private class ArrayGenMethod extends GenMethod { ArrayGenMethod() { this = type.getName() + "genmethod" } override predicate appliesTo(Type t, Content c) { - t = type and + replaceTypeVariable(t.(Array).getElementType()) = type.getElementType() and c instanceof ArrayContent } From 97faeb026f42b4155d87f07a57766ba5897936cc Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 25 Aug 2021 17:16:16 -0700 Subject: [PATCH 376/429] Fix side of stack that gen method types are used --- java/ql/src/utils/FlowTestCase.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 6d1b3dbc4f6..6c6b56b0e10 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -240,7 +240,7 @@ class TestCase extends TTestCase { or exists(SummaryComponentStack s | s.tail() = stack | // we currently only know the type if the stack is one level in - if s = input + if stack = baseInput then result = SupportMethod::genMethodFor(this.getInputType(), s).getCall(this.getInput(s)) else result = SupportMethod::genMethodForContent(s).getCall(this.getInput(s)) ) From 04e04b30315d2194e3560bbe208702153c93f3ca Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Fri, 27 Aug 2021 10:38:02 -0700 Subject: [PATCH 377/429] Use array allocation syntax --- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index ea7c6c4d7c7..af52cb7bb70 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -383,12 +383,12 @@ private class ArrayGenMethod extends GenMethod { ArrayGenMethod() { this = type.getName() + "genmethod" } override predicate appliesTo(Type t, Content c) { - replaceTypeVariable(t.(Array).getElementType()) = type.getElementType() and + replaceTypeVariable(t.(Array).getComponentType()) = type.getComponentType() and c instanceof ArrayContent } bindingset[arg] override string getCall(string arg) { - result = "{" + getConvertExprIfNotObject(type.getElementType()) + arg + "}" + result = "new " + getShortNameIfPossible(type) + "{" + getConvertExprIfNotObject(type.getComponentType()) + arg + "}" } } From 23b9028d2cd4db8502e87725bbd88ef8324c23e0 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Fri, 27 Aug 2021 11:20:44 -0700 Subject: [PATCH 378/429] Correctly determine which support method definitions are required --- java/ql/src/utils/FlowTestCase.qll | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 6c6b56b0e10..1759b56f99b 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -267,8 +267,12 @@ class TestCase extends TTestCase { * Returns the definition of a `newWith` method needed to set up the input or a `get` method needed to set up the output for this test. */ SupportMethod getASupportMethod() { - result = SupportMethod::genMethodFor(this.getInputType(), input) or - result = SupportMethod::genMethodForContent(input.tail().drop(_)) or + exists(SummaryComponentStack s | s = input.drop(_) and s.tail() != baseInput | + result = SupportMethod::genMethodForContent(s) + ) or + exists(SummaryComponentStack s | s = input.drop(_) and s.tail() = baseInput | + result = SupportMethod::genMethodFor(this.getInputType(), s) + ) or result = SupportMethod::getMethodFor(this.getOutputType(), output) or result = SupportMethod::getMethodForContent(output.tail().drop(_)) } From adcb90aa8ca1e0290a153c2419d196d2476ab3ee Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Fri, 27 Aug 2021 11:24:50 -0700 Subject: [PATCH 379/429] fixup generateflowtestcase chaneg --- java/ql/src/utils/GenerateFlowTestCase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/utils/GenerateFlowTestCase.py b/java/ql/src/utils/GenerateFlowTestCase.py index 757a94fe92d..15bdfc2eb87 100755 --- a/java/ql/src/utils/GenerateFlowTestCase.py +++ b/java/ql/src/utils/GenerateFlowTestCase.py @@ -127,7 +127,7 @@ queryDir = os.path.join(workDir, "query") os.makedirs(queryDir) qlFile = os.path.join(queryDir, "gen.ql") with open(os.path.join(queryDir, "qlpack.yml"), "w") as f: - f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql-java") + f.write("name: test-generation-query\nversion: 0.0.0\nlibraryPathDependencies: codeql/java-queries") with open(qlFile, "w") as f: f.write( "import java\nimport utils.GenerateFlowTestCase\n\nclass GenRow extends TargetSummaryModelCsv {\n\n\toverride predicate row(string r) {\n\t\tr = [\n") From b28e956dd2446e4c60a04ec981c1117e4d45a0bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 00:08:31 +0000 Subject: [PATCH 380/429] Add changed framework coverage reports --- java/documentation/library-coverage/coverage.csv | 2 +- java/documentation/library-coverage/coverage.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index e8ce26b8fc5..b8de8cf3c3f 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -23,7 +23,7 @@ java.lang,,,3,,,,,,,,,,,,,,,,,,,1,2 java.net,10,3,7,,,,,,,,,,,10,,,,,,,3,7, java.nio,10,,4,,10,,,,,,,,,,,,,,,,,4, java.sql,7,,,,,,,,,,,,,,,7,,,,,,, -java.util,,,332,,,,,,,,,,,,,,,,,,,15,317 +java.util,,,336,,,,,,,,,,,,,,,,,,,15,321 javax.json,,,123,,,,,,,,,,,,,,,,,,,100,23 javax.management.remote,2,,,,,,,,,2,,,,,,,,,,,,, javax.naming,7,,,,,,,,,6,1,,,,,,,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index 3ccf089f092..a89ded5c50c 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -15,9 +15,9 @@ Java framework & library support `Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25 `Google Guava `_,``com.google.common.*``,,175,6,,6,,,,, `JSON-java `_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,371,30,13,,,7,,,10 + Java Standard Library,``java.*``,3,375,30,13,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",22,540,27,,,,,1,1,2 `Spring `_,``org.springframework.*``,29,469,91,,,,19,14,,29 Others,"``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jooq``, ``org.mvel2``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``",7,25,146,,,,14,18,, - Totals,,84,3491,398,13,6,6,107,33,1,66 + Totals,,84,3495,398,13,6,6,107,33,1,66 From f5a1a124350e5363c4267cdd82f298b93a0d108f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 29 Aug 2021 12:03:27 +0200 Subject: [PATCH 381/429] support case insensitive regexps in the ReDoS queries --- config/identical-files.json | 2 +- .../security/performance/ReDoSUtil.qll | 81 ++++++++++++++++--- .../security/performance/RegExpTreeView.qll | 38 +++++++++ .../ReDoS/PolynomialBackTracking.expected | 4 + .../Performance/ReDoS/ReDoS.expected | 2 + .../test/query-tests/Performance/ReDoS/tst.js | 8 +- python/ql/lib/semmle/python/RegexTreeView.qll | 8 ++ .../python/security/performance/ReDoSUtil.qll | 81 ++++++++++++++++--- .../security/performance/RegExpTreeView.qll | 29 +++++++ 9 files changed, 233 insertions(+), 20 deletions(-) diff --git a/config/identical-files.json b/config/identical-files.json index 037b0126cb3..74ef7b82323 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -462,4 +462,4 @@ "javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll", "python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll" ] -} +} \ No newline at end of file diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 43601b1d407..cdd42ce1540 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -164,6 +164,7 @@ class RelevantRegExpTerm extends RegExpTerm { /** * Holds if `term` is the chosen canonical representative for all terms with string representation `str`. + * The string representation includes which flags are used with the regular expression. * * 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. @@ -173,26 +174,54 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { min(RelevantRegExpTerm t, Location loc, File file | loc = t.getLocation() and file = t.getFile() and - str = t.getRawValue() + str = t.getRawValue() + "|" + getCanonicalizationFlags(t.getRootTerm()) | t order by t.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn() ) } +/** + * Gets a string reperesentation of the flags used with the regular expression. + * Only the flags that are relevant for the canonicalization are included. + */ +string getCanonicalizationFlags(RegExpTerm root) { + root.isRootTerm() and + ( + RegExpFlags::isIgnoreCase(root) and + result = "i" + or + not RegExpFlags::isIgnoreCase(root) and + result = "" + ) +} + /** * 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 | cc instanceof RelevantRegExpTerm).getValue().charAt(_) + c = + any(RegexpCharacterConstant cc | + cc instanceof RelevantRegExpTerm and + not RegExpFlags::isIgnoreCase(cc.getRootTerm()) + ).getValue().charAt(_) + or + // normalize to lower case if the regexp is case insensitive + c = + any(RegexpCharacterConstant cc, string char | + cc instanceof RelevantRegExpTerm and + RegExpFlags::isIgnoreCase(cc.getRootTerm()) and + char = cc.getValue().charAt(_) + | + char.toLowerCase() + ) } or /** * An input symbol representing all characters matched by * a (non-universal) character class that has string representation `charClassString`. */ CharClass(string charClassString) { - exists(RelevantRegExpTerm term | term.getRawValue() = charClassString) and exists(RelevantRegExpTerm recc | isCanonicalTerm(recc, charClassString) | recc instanceof RegExpCharacterClass and not recc.(RegExpCharacterClass).isUniversalClass() @@ -293,6 +322,19 @@ private module CharacterClasses { */ pragma[noinline] predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { + if RegExpFlags::isIgnoreCase(cc.getRootTerm()) + then + // normalize everything to lower case if the regexp is case insensitive + exists(string c | hasChildThatMatchesIgnoringCasing(cc, c) | char = c.toLowerCase()) + else hasChildThatMatchesIgnoringCasing(cc, char) + } + + /** + * Holds if the character class `cc` has a child (constant or range) that matches `char`. + * Ignores whether the character class is inside a regular expression that ignores casing. + */ + pragma[noinline] + predicate hasChildThatMatchesIgnoringCasing(RegExpCharacterClass cc, string char) { exists(getCanonicalCharClass(cc)) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() @@ -508,7 +550,7 @@ 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) { +State after(RegExpTerm t) { exists(RegExpAlt alt | t = alt.getAChild() | result = after(alt)) or exists(RegExpSequence seq, int i | t = seq.getChild(i) | @@ -537,7 +579,14 @@ private State after(RegExpTerm t) { 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 + ( + not RegExpFlags::isIgnoreCase(s.getRootTerm()) and + lbl = Char(s.getValue().charAt(i)) + or + // normalizing to lower case if ignorecase flag is set + RegExpFlags::isIgnoreCase(s.getRootTerm()) and + exists(string c | c = s.getValue().charAt(i) | lbl = Char(c.toLowerCase())) + ) and ( q2 = Match(s, i + 1) or @@ -547,20 +596,20 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { ) or exists(RegExpDot dot | q1 = before(dot) and q2 = after(dot) | - if dot.getLiteral().isDotAll() then lbl = Any() else lbl = Dot() + if RegExpFlags::isDotAll(dot.getRootTerm()) 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.getRawValue()) and + lbl = CharClass(cc.getRawValue() + "|" + getCanonicalizationFlags(cc.getRootTerm())) and q2 = after(cc) ) or exists(RegExpCharacterClassEscape cc | q1 = before(cc) and - lbl = CharClass(cc.getRawValue()) and + lbl = CharClass(cc.getRawValue() + "|" + getCanonicalizationFlags(cc.getRootTerm())) and q2 = after(cc) ) or @@ -627,13 +676,27 @@ RegExpRoot getRoot(RegExpTerm term) { result = getRoot(term.getParent()) } -private newtype TState = +/** + * A state in the NFA. + */ +newtype TState = + /** + * A state representing that the NFA is about to match a term. + * `i` is used to index into multi-char literals. + */ Match(RelevantRegExpTerm t, int i) { i = 0 or exists(t.(RegexpCharacterConstant).getValue().charAt(i)) } or + /** + * An accept state, where exactly the given input string is accepted. + */ Accept(RegExpRoot l) { l.isRelevant() } or + /** + * An accept state, where the given input string, or any string that has this + * string as a prefix, is accepted. + */ AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } /** diff --git a/javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll b/javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll index f730f62f5b8..f896e44f5e9 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/RegExpTreeView.qll @@ -12,3 +12,41 @@ import javascript * For javascript we make the pragmatic performance optimization to ignore minified files. */ predicate isExcluded(RegExpParent parent) { parent.(Expr).getTopLevel().isMinified() } + +/** + * A module containing predicates for determining which flags a regular expression have. + */ +module RegExpFlags { + /** + * Holds if `root` has the `i` flag for case-insensitive matching. + */ + predicate isIgnoreCase(RegExpTerm root) { + root.isRootTerm() and + exists(DataFlow::RegExpCreationNode node | node.getRoot() = root | + RegExp::isIgnoreCase(node.getFlags()) + ) + } + + /** + * Gets the flags for `root`, or the empty string if `root` has no flags. + */ + string getFlags(RegExpTerm root) { + root.isRootTerm() and + exists(DataFlow::RegExpCreationNode node | node.getRoot() = root | + result = node.getFlags() + or + not exists(node.getFlags()) and + result = "" + ) + } + + /** + * Holds if `root` has the `s` flag for multi-line matching. + */ + predicate isDotAll(RegExpTerm root) { + root.isRootTerm() and + exists(DataFlow::RegExpCreationNode node | node.getRoot() = root | + RegExp::isDotAll(node.getFlags()) + ) + } +} diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 9dce8af29ad..e38b5f9326d 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -502,3 +502,7 @@ | tst.js:375:15:375:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$\|y) | | tst.js:378:16:378:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$) | | tst.js:379:16:379:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$\|y) | +| tst.js:381:15:381:24 | (foo\|FOO)* | Strings with many repetitions of 'FOO' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | +| tst.js:382:14:382:23 | (foo\|FOO)* | Strings with many repetitions of 'foo' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | +| tst.js:384:15:384:26 | ([AB]\|[ab])* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding ([AB]\|[ab])*C | +| tst.js:385:14:385:25 | ([DE]\|[de])* | Strings with many repetitions of 'd' can start matching anywhere after the start of the preceeding ([DE]\|[de])*F | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected index 05352f7a20d..fe23342eb02 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/ReDoS.expected @@ -178,3 +178,5 @@ | tst.js:375:15:375:16 | x* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'x'. | | tst.js:378:16:378:22 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | | tst.js:379:16:379:22 | [\\s\\S]* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. | +| tst.js:382:14:382:23 | (foo\|FOO)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'foo'. | +| tst.js:385:14:385:25 | ([DE]\|[de])* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'd'. | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 762929080ae..c3521343111 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -376,4 +376,10 @@ var bad90 = /(x*)+(?=$|y)/ // GOOD - but we spuriously conclude that a rejecting suffix exists. var good44 = /([\s\S]*)+(?=$)/; -var good45 = /([\s\S]*)+(?=$|y)/; \ No newline at end of file +var good45 = /([\s\S]*)+(?=$|y)/; + +var good46 = /(foo|FOO)*bar/; +var bad91 = /(foo|FOO)*bar/i; + +var good47 = /([AB]|[ab])*C/; +var bad92 = /([DE]|[de])*F/i; diff --git a/python/ql/lib/semmle/python/RegexTreeView.qll b/python/ql/lib/semmle/python/RegexTreeView.qll index cc4c08c6364..784ea06ca29 100644 --- a/python/ql/lib/semmle/python/RegexTreeView.qll +++ b/python/ql/lib/semmle/python/RegexTreeView.qll @@ -61,6 +61,14 @@ class RegExpLiteral extends TRegExpLiteral, RegExpParent { predicate isDotAll() { re.getAMode() = "DOTALL" } + predicate isIgnoreCase() { re.getAMode() = "IGNORECASE" } + + string getFlags() { + not exists(re.getAMode()) and result = "" + or + result = strictconcat(string mode | mode = re.getAMode() | mode, " | ") + } + override Regex getRegex() { result = re } string getPrimaryQLClass() { result = "RegExpLiteral" } diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index 43601b1d407..cdd42ce1540 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -164,6 +164,7 @@ class RelevantRegExpTerm extends RegExpTerm { /** * Holds if `term` is the chosen canonical representative for all terms with string representation `str`. + * The string representation includes which flags are used with the regular expression. * * 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. @@ -173,26 +174,54 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { min(RelevantRegExpTerm t, Location loc, File file | loc = t.getLocation() and file = t.getFile() and - str = t.getRawValue() + str = t.getRawValue() + "|" + getCanonicalizationFlags(t.getRootTerm()) | t order by t.getFile().getRelativePath(), loc.getStartLine(), loc.getStartColumn() ) } +/** + * Gets a string reperesentation of the flags used with the regular expression. + * Only the flags that are relevant for the canonicalization are included. + */ +string getCanonicalizationFlags(RegExpTerm root) { + root.isRootTerm() and + ( + RegExpFlags::isIgnoreCase(root) and + result = "i" + or + not RegExpFlags::isIgnoreCase(root) and + result = "" + ) +} + /** * 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 | cc instanceof RelevantRegExpTerm).getValue().charAt(_) + c = + any(RegexpCharacterConstant cc | + cc instanceof RelevantRegExpTerm and + not RegExpFlags::isIgnoreCase(cc.getRootTerm()) + ).getValue().charAt(_) + or + // normalize to lower case if the regexp is case insensitive + c = + any(RegexpCharacterConstant cc, string char | + cc instanceof RelevantRegExpTerm and + RegExpFlags::isIgnoreCase(cc.getRootTerm()) and + char = cc.getValue().charAt(_) + | + char.toLowerCase() + ) } or /** * An input symbol representing all characters matched by * a (non-universal) character class that has string representation `charClassString`. */ CharClass(string charClassString) { - exists(RelevantRegExpTerm term | term.getRawValue() = charClassString) and exists(RelevantRegExpTerm recc | isCanonicalTerm(recc, charClassString) | recc instanceof RegExpCharacterClass and not recc.(RegExpCharacterClass).isUniversalClass() @@ -293,6 +322,19 @@ private module CharacterClasses { */ pragma[noinline] predicate hasChildThatMatches(RegExpCharacterClass cc, string char) { + if RegExpFlags::isIgnoreCase(cc.getRootTerm()) + then + // normalize everything to lower case if the regexp is case insensitive + exists(string c | hasChildThatMatchesIgnoringCasing(cc, c) | char = c.toLowerCase()) + else hasChildThatMatchesIgnoringCasing(cc, char) + } + + /** + * Holds if the character class `cc` has a child (constant or range) that matches `char`. + * Ignores whether the character class is inside a regular expression that ignores casing. + */ + pragma[noinline] + predicate hasChildThatMatchesIgnoringCasing(RegExpCharacterClass cc, string char) { exists(getCanonicalCharClass(cc)) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() @@ -508,7 +550,7 @@ 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) { +State after(RegExpTerm t) { exists(RegExpAlt alt | t = alt.getAChild() | result = after(alt)) or exists(RegExpSequence seq, int i | t = seq.getChild(i) | @@ -537,7 +579,14 @@ private State after(RegExpTerm t) { 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 + ( + not RegExpFlags::isIgnoreCase(s.getRootTerm()) and + lbl = Char(s.getValue().charAt(i)) + or + // normalizing to lower case if ignorecase flag is set + RegExpFlags::isIgnoreCase(s.getRootTerm()) and + exists(string c | c = s.getValue().charAt(i) | lbl = Char(c.toLowerCase())) + ) and ( q2 = Match(s, i + 1) or @@ -547,20 +596,20 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { ) or exists(RegExpDot dot | q1 = before(dot) and q2 = after(dot) | - if dot.getLiteral().isDotAll() then lbl = Any() else lbl = Dot() + if RegExpFlags::isDotAll(dot.getRootTerm()) 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.getRawValue()) and + lbl = CharClass(cc.getRawValue() + "|" + getCanonicalizationFlags(cc.getRootTerm())) and q2 = after(cc) ) or exists(RegExpCharacterClassEscape cc | q1 = before(cc) and - lbl = CharClass(cc.getRawValue()) and + lbl = CharClass(cc.getRawValue() + "|" + getCanonicalizationFlags(cc.getRootTerm())) and q2 = after(cc) ) or @@ -627,13 +676,27 @@ RegExpRoot getRoot(RegExpTerm term) { result = getRoot(term.getParent()) } -private newtype TState = +/** + * A state in the NFA. + */ +newtype TState = + /** + * A state representing that the NFA is about to match a term. + * `i` is used to index into multi-char literals. + */ Match(RelevantRegExpTerm t, int i) { i = 0 or exists(t.(RegexpCharacterConstant).getValue().charAt(i)) } or + /** + * An accept state, where exactly the given input string is accepted. + */ Accept(RegExpRoot l) { l.isRelevant() } or + /** + * An accept state, where the given input string, or any string that has this + * string as a prefix, is accepted. + */ AcceptAnySuffix(RegExpRoot l) { l.isRelevant() } /** diff --git a/python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll b/python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll index 56a6c90ffde..4fbe32f7e7e 100644 --- a/python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll +++ b/python/ql/lib/semmle/python/security/performance/RegExpTreeView.qll @@ -18,3 +18,32 @@ predicate isExcluded(RegExpParent parent) { // we explicitly exclude these. count(int i | exists(parent.getRegex().getText().regexpFind("\\.\\*", i, _)) | i) > 10 } + +/** + * A module containing predicates for determining which flags a regular expression have. + */ +module RegExpFlags { + /** + * Holds if `root` has the `i` flag for case-insensitive matching. + */ + predicate isIgnoreCase(RegExpTerm root) { + root.isRootTerm() and + root.getLiteral().isIgnoreCase() + } + + /** + * Gets the flags for `root`, or the empty string if `root` has no flags. + */ + string getFlags(RegExpTerm root) { + root.isRootTerm() and + result = root.getLiteral().getFlags() + } + + /** + * Holds if `root` has the `s` flag for multi-line matching. + */ + predicate isDotAll(RegExpTerm root) { + root.isRootTerm() and + root.getLiteral().isDotAll() + } +} From 486b283c208a8b9e098709a9b96373e6cee062c0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 11:05:32 +0200 Subject: [PATCH 382/429] support the "module" field in `package.json` files --- .../lib/semmle/javascript/NodeModuleResolutionImpl.qll | 2 +- .../Performance/ReDoS/PolynomialBackTracking.expected | 1 + .../Performance/ReDoS/PolynomialReDoS.expected | 9 +++++++++ .../Performance/ReDoS/lib/moduleLib/moduleLib.js | 3 +++ .../Performance/ReDoS/lib/moduleLib/package.json | 6 ++++++ 5 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/moduleLib.js create mode 100644 javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/package.json diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 4e23898dbcd..cb2481861ee 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -146,7 +146,7 @@ private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] } class MainModulePath extends PathExpr, @json_string { PackageJSON pkg; - MainModulePath() { this = pkg.getPropValue("main") } + MainModulePath() { this = pkg.getPropValue(["main", "module"]) } /** Gets the `package.json` file in which this path occurs. */ PackageJSON getPackageJSON() { result = pkg } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 9dce8af29ad..4509b2f7e57 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -30,6 +30,7 @@ | 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 | +| lib/moduleLib/moduleLib.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | lib/otherLib/js/src/index.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | lib/sublib/factory.js:13:14:13:15 | 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 b705b1b4f31..bd49ef91504 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -11,6 +11,10 @@ nodes | lib/lib.js:7:19:7:22 | name | | lib/lib.js:8:13:8:16 | name | | lib/lib.js:8:13:8:16 | name | +| lib/moduleLib/moduleLib.js:1:28:1:31 | name | +| lib/moduleLib/moduleLib.js:1:28:1:31 | name | +| lib/moduleLib/moduleLib.js:2:13:2:16 | name | +| lib/moduleLib/moduleLib.js:2:13:2:16 | name | | lib/otherLib/js/src/index.js:1:28:1:31 | name | | lib/otherLib/js/src/index.js:1:28:1:31 | name | | lib/otherLib/js/src/index.js:2:13:2:16 | name | @@ -174,6 +178,10 @@ edges | 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/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | +| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | +| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | +| lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | | lib/otherLib/js/src/index.js:1:28:1:31 | name | lib/otherLib/js/src/index.js:2:13:2:16 | name | | lib/otherLib/js/src/index.js:1:28:1:31 | name | lib/otherLib/js/src/index.js:2:13:2:16 | name | | lib/otherLib/js/src/index.js:1:28:1:31 | name | lib/otherLib/js/src/index.js:2:13:2:16 | name | @@ -323,6 +331,7 @@ edges | 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 | +| lib/moduleLib/moduleLib.js:2:2:2:17 | /a*b/.test(name) | lib/moduleLib/moduleLib.js:1:28:1:31 | name | lib/moduleLib/moduleLib.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/moduleLib/moduleLib.js:2:3:2:4 | a* | regular expression | lib/moduleLib/moduleLib.js:1:28:1:31 | name | library input | | lib/otherLib/js/src/index.js:2:2:2:17 | /a*b/.test(name) | lib/otherLib/js/src/index.js:1:28:1:31 | name | lib/otherLib/js/src/index.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/otherLib/js/src/index.js:2:3:2:4 | a* | regular expression | lib/otherLib/js/src/index.js:1:28:1:31 | name | library input | | lib/sublib/factory.js:13:13:13:28 | /f*g/.test(name) | lib/sublib/factory.js:12:26:12:29 | name | lib/sublib/factory.js:13:24:13:27 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/sublib/factory.js:13:14:13:15 | f* | regular expression | lib/sublib/factory.js:12:26:12:29 | 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/moduleLib/moduleLib.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/moduleLib.js new file mode 100644 index 00000000000..4326227e86b --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/moduleLib.js @@ -0,0 +1,3 @@ +module.exports = function (name) { + /a*b/.test(name); // NOT OK +}; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/package.json b/javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/package.json new file mode 100644 index 00000000000..f4e13351e8b --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/moduleLib/package.json @@ -0,0 +1,6 @@ +{ + "name": "my-other-lib", + "version": "0.0.7", + "main": "./js/src/does-not-exist.js", + "module": "./moduleLib.js" +} \ No newline at end of file From 5dddc48e60cf4e3e5c86fd019abc924599b47845 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 11:53:13 +0100 Subject: [PATCH 383/429] autoformat --- java/ql/src/utils/FlowTestCase.qll | 9 ++++++--- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 1759b56f99b..33459ed790c 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -269,11 +269,14 @@ class TestCase extends TTestCase { SupportMethod getASupportMethod() { exists(SummaryComponentStack s | s = input.drop(_) and s.tail() != baseInput | result = SupportMethod::genMethodForContent(s) - ) or + ) + or exists(SummaryComponentStack s | s = input.drop(_) and s.tail() = baseInput | result = SupportMethod::genMethodFor(this.getInputType(), s) - ) or - result = SupportMethod::getMethodFor(this.getOutputType(), output) or + ) + or + result = SupportMethod::getMethodFor(this.getOutputType(), output) + or result = SupportMethod::getMethodForContent(output.tail().drop(_)) } diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index af52cb7bb70..e19609a9ee0 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -389,6 +389,8 @@ private class ArrayGenMethod extends GenMethod { bindingset[arg] override string getCall(string arg) { - result = "new " + getShortNameIfPossible(type) + "{" + getConvertExprIfNotObject(type.getComponentType()) + arg + "}" + result = + "new " + getShortNameIfPossible(type) + "{" + + getConvertExprIfNotObject(type.getComponentType()) + arg + "}" } } From 510f5abb9a858596ac3389ff1dac87f6b226dd3b Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 11:56:03 +0100 Subject: [PATCH 384/429] Add missing qldoc --- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index e19609a9ee0..934f30fa301 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -371,6 +371,9 @@ private class MapGenValueMethod extends GenMethod { override string getCall(string arg) { result = "Map.of(null, " + arg + ")" } } +/** + * Returns a cast to type `t` if `t` is not `java.lang.Object`, or an empty string otherwise. + */ string getConvertExprIfNotObject(RefType t) { if t.hasQualifiedName("java.lang", "Object") then result = "" From f94d8c341d9c3ee373a580b2daa584a6554f5e7a Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 11:57:49 +0100 Subject: [PATCH 385/429] Abbreviate multi-column `min` --- java/ql/src/utils/FlowTestCaseSupportMethods.qll | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/java/ql/src/utils/FlowTestCaseSupportMethods.qll b/java/ql/src/utils/FlowTestCaseSupportMethods.qll index 934f30fa301..fd19f555f79 100644 --- a/java/ql/src/utils/FlowTestCaseSupportMethods.qll +++ b/java/ql/src/utils/FlowTestCaseSupportMethods.qll @@ -67,10 +67,7 @@ module SupportMethod { /** Gets a generator method for the type `t` and the content type of the head of the component stack `c`. */ GenMethod genMethodFor(Type t, SummaryComponentStack c) { - result = - min(GenMethod g | - g = min(GenMethod g1 | g1.appliesTo(t, getContent(c.head())) | g1 order by g1.getPriority()) - ) + result = min(GenMethod g | g.appliesTo(t, getContent(c.head())) | g order by g.getPriority(), g) } /** Gets a getter method for the content type of the head of the component stack `c`. */ @@ -80,10 +77,7 @@ module SupportMethod { /** Gets a getter method for the type `t` and the content type of the head of the component stack `c`. */ GetMethod getMethodFor(Type t, SummaryComponentStack c) { - result = - min(GetMethod g | - g = min(GetMethod g1 | g1.appliesTo(t, getContent(c.head())) | g1 order by g1.getPriority()) - ) + result = min(GetMethod g | g.appliesTo(t, getContent(c.head())) | g order by g.getPriority(), g) } } From c6399dbdf43056344b4f757444c0d2ef044a2184 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 23:10:05 +0200 Subject: [PATCH 386/429] simplify the `connect` model by reusing `NodeJSLib::RouteHandler` --- .../semmle/javascript/frameworks/Connect.qll | 83 ++----------------- .../frameworks/connect/RequestExpr.qll | 2 +- .../frameworks/connect/ResponseExpr.qll | 2 +- 3 files changed, 8 insertions(+), 79 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll index 5d1e36369a7..e9829bd78e5 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll @@ -24,7 +24,8 @@ module Connect { * but support for other kinds of route handlers can be added by implementing * additional subclasses of this class. */ - abstract class RouteHandler extends HTTP::Servers::StandardRouteHandler, DataFlow::ValueNode { + abstract class RouteHandler extends HTTP::Servers::StandardRouteHandler, NodeJSLib::RouteHandler, + DataFlow::ValueNode { /** * Gets the parameter of kind `kind` of this route handler. * @@ -35,12 +36,12 @@ module Connect { /** * Gets the parameter of the route handler that contains the request object. */ - Parameter getRequestParameter() { result = getRouteHandlerParameter("request") } + override Parameter getRequestParameter() { result = getRouteHandlerParameter("request") } /** * Gets the parameter of the route handler that contains the response object. */ - Parameter getResponseParameter() { result = getRouteHandlerParameter("response") } + override Parameter getResponseParameter() { result = getRouteHandlerParameter("response") } } /** @@ -56,50 +57,6 @@ module Connect { } } - /** - * A Connect response source, that is, the response parameter of a - * route handler. - */ - private class ResponseSource extends HTTP::Servers::ResponseSource { - RouteHandler rh; - - ResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) } - - /** - * Gets the route handler that provides this response. - */ - override RouteHandler getRouteHandler() { result = rh } - } - - /** - * A Connect request source, that is, the request parameter of a - * route handler. - */ - private class RequestSource extends HTTP::Servers::RequestSource { - RouteHandler rh; - - RequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) } - - /** - * Gets the route handler that handles this request. - */ - override RouteHandler getRouteHandler() { result = rh } - } - - /** - * A Node.js HTTP response provided by Connect. - */ - class ResponseExpr extends NodeJSLib::ResponseExpr { - ResponseExpr() { src instanceof ResponseSource } - } - - /** - * A Node.js HTTP request provided by Connect. - */ - class RequestExpr extends NodeJSLib::RequestExpr { - RequestExpr() { src instanceof RequestSource } - } - /** * A call to a Connect method that sets up a route. */ @@ -156,10 +113,11 @@ module Connect { * An access to a user-controlled Connect request input. */ private class RequestInputAccess extends HTTP::RequestInputAccess { - RequestExpr request; + NodeJSLib::RequestExpr request; string kind; RequestInputAccess() { + request.getRouteHandler() instanceof StandardRouteHandler and exists(PropAccess cookies | // `req.cookies.get()` kind = "cookie" and @@ -172,33 +130,4 @@ module Connect { override string getKind() { result = kind } } - - /** - * A function that flows to a route setup. - */ - private class TrackedRouteHandlerCandidateWithSetup extends RouteHandler, - HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode { - TrackedRouteHandlerCandidateWithSetup() { this = any(RouteSetup s).getARouteHandler() } - - override Parameter getRouteHandlerParameter(string kind) { - result = getRouteHandlerParameter(astNode, kind) - } - } - - /** - * A call that looks like a route setup on a Connect server. - * - * For example, this could be the call `router.use(handler)` where - * it is unknown if `router` is a Connect router. - */ - class RouteSetupCandidate extends HTTP::RouteSetupCandidate, DataFlow::MethodCallNode { - DataFlow::ValueNode routeHandlerArg; - - RouteSetupCandidate() { - getMethodName() = "use" and - routeHandlerArg = getAnArgument() - } - - override DataFlow::ValueNode getARouteHandlerArg() { result = routeHandlerArg } - } } diff --git a/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll index 272b7d3a0c9..d920b2edbfe 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll +++ b/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll @@ -1,5 +1,5 @@ import javascript -query predicate test_RequestExpr(Connect::RequestExpr e, HTTP::RouteHandler res) { +query predicate test_RequestExpr(HTTP::RequestExpr e, HTTP::RouteHandler res) { res = e.getRouteHandler() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll index 6094e131af7..2b5447fb6dd 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll +++ b/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll @@ -1,5 +1,5 @@ import javascript -query predicate test_ResponseExpr(Connect::ResponseExpr e, HTTP::RouteHandler res) { +query predicate test_ResponseExpr(HTTP::ResponseExpr e, HTTP::RouteHandler res) { res = e.getRouteHandler() } From 3d6ab81ab88cb409b66a53b090c534ac84db3d1a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 23:32:12 +0200 Subject: [PATCH 387/429] refactor the tests for `connect` --- .../frameworks/connect/Credentials.qll | 5 -- .../frameworks/connect/HeaderDefinition.qll | 5 -- .../connect/HeaderDefinition_defines.qll | 5 -- .../HeaderDefinition_getAHeaderName.qll | 5 -- .../frameworks/connect/RequestExpr.qll | 5 -- .../frameworks/connect/RequestInputAccess.qll | 7 -- .../frameworks/connect/ResponseExpr.qll | 5 -- .../frameworks/connect/RouteHandler.qll | 3 - .../connect/RouteHandler_getARequestExpr.qll | 5 -- .../connect/RouteHandler_getAResponseExpr.qll | 5 -- .../RouteHandler_getAResponseHeader.qll | 7 -- .../frameworks/connect/RouteSetup.qll | 3 - .../connect/RouteSetup_getARouteHandler.qll | 5 -- .../connect/RouteSetup_getServer.qll | 3 - .../frameworks/connect/ServerDefinition.qll | 3 - .../library-tests/frameworks/connect/tests.ql | 72 +++++++++++++++---- 16 files changed, 57 insertions(+), 86 deletions(-) delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/Credentials.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_defines.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_getAHeaderName.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RequestInputAccess.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteHandler.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getARequestExpr.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseExpr.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseHeader.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteSetup.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getARouteHandler.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getServer.qll delete mode 100644 javascript/ql/test/library-tests/frameworks/connect/ServerDefinition.qll diff --git a/javascript/ql/test/library-tests/frameworks/connect/Credentials.qll b/javascript/ql/test/library-tests/frameworks/connect/Credentials.qll deleted file mode 100644 index 11ba980db94..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/Credentials.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_Credentials(Connect::Credentials cr, string res) { - res = cr.getCredentialsKind() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition.qll b/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition.qll deleted file mode 100644 index 022fcaba347..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_HeaderDefinition(HTTP::HeaderDefinition hd, Connect::RouteHandler rh) { - rh = hd.getRouteHandler() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_defines.qll b/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_defines.qll deleted file mode 100644 index 72a211ccc30..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_defines.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_HeaderDefinition_defines(HTTP::HeaderDefinition hd, string name, string value) { - hd.defines(name, value) and hd.getRouteHandler() instanceof Connect::RouteHandler -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_getAHeaderName.qll b/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_getAHeaderName.qll deleted file mode 100644 index 1f6438a5130..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/HeaderDefinition_getAHeaderName.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_HeaderDefinition_getAHeaderName(HTTP::HeaderDefinition hd, string res) { - hd.getRouteHandler() instanceof Connect::RouteHandler and res = hd.getAHeaderName() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll deleted file mode 100644 index d920b2edbfe..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RequestExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_RequestExpr(HTTP::RequestExpr e, HTTP::RouteHandler res) { - res = e.getRouteHandler() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RequestInputAccess.qll b/javascript/ql/test/library-tests/frameworks/connect/RequestInputAccess.qll deleted file mode 100644 index 92afccc9bda..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RequestInputAccess.qll +++ /dev/null @@ -1,7 +0,0 @@ -import javascript - -query predicate test_RequestInputAccess( - HTTP::RequestInputAccess ria, string res, Connect::RouteHandler rh -) { - ria.getRouteHandler() = rh and res = ria.getKind() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll deleted file mode 100644 index 2b5447fb6dd..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/ResponseExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_ResponseExpr(HTTP::ResponseExpr e, HTTP::RouteHandler res) { - res = e.getRouteHandler() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteHandler.qll deleted file mode 100644 index 77d95f676c2..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler.qll +++ /dev/null @@ -1,3 +0,0 @@ -import javascript - -query predicate test_RouteHandler(Connect::RouteHandler rh, Expr res) { res = rh.getServer() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getARequestExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getARequestExpr.qll deleted file mode 100644 index 26ad5db877e..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getARequestExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -import semmle.javascript.frameworks.Express - -query predicate test_RouteHandler_getARequestExpr(Connect::RouteHandler rh, HTTP::RequestExpr res) { - res = rh.getARequestExpr() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseExpr.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseExpr.qll deleted file mode 100644 index 48674882b7c..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -import semmle.javascript.frameworks.Express - -query predicate test_RouteHandler_getAResponseExpr(Connect::RouteHandler rh, HTTP::ResponseExpr res) { - res = rh.getAResponseExpr() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseHeader.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseHeader.qll deleted file mode 100644 index d3a3cbd8fe4..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteHandler_getAResponseHeader.qll +++ /dev/null @@ -1,7 +0,0 @@ -import semmle.javascript.frameworks.Express - -query predicate test_RouteHandler_getAResponseHeader( - Connect::RouteHandler rh, string name, HTTP::HeaderDefinition res -) { - res = rh.getAResponseHeader(name) -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteSetup.qll deleted file mode 100644 index 29fea40d518..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup.qll +++ /dev/null @@ -1,3 +0,0 @@ -import javascript - -query predicate test_RouteSetup(Connect::RouteSetup rs) { any() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getARouteHandler.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getARouteHandler.qll deleted file mode 100644 index 6e3d66abb5c..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getARouteHandler.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_RouteSetup_getARouteHandler(Connect::RouteSetup r, DataFlow::SourceNode res) { - res = r.getARouteHandler() -} diff --git a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getServer.qll b/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getServer.qll deleted file mode 100644 index 58f208d5f45..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/RouteSetup_getServer.qll +++ /dev/null @@ -1,3 +0,0 @@ -import javascript - -query predicate test_RouteSetup_getServer(Connect::RouteSetup rs, Expr res) { res = rs.getServer() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/ServerDefinition.qll b/javascript/ql/test/library-tests/frameworks/connect/ServerDefinition.qll deleted file mode 100644 index b21f5bc196f..00000000000 --- a/javascript/ql/test/library-tests/frameworks/connect/ServerDefinition.qll +++ /dev/null @@ -1,3 +0,0 @@ -import javascript - -query predicate test_ServerDefinition(Connect::ServerDefinition s) { any() } diff --git a/javascript/ql/test/library-tests/frameworks/connect/tests.ql b/javascript/ql/test/library-tests/frameworks/connect/tests.ql index a99bef7726f..24ddefeaf5d 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/tests.ql +++ b/javascript/ql/test/library-tests/frameworks/connect/tests.ql @@ -1,15 +1,57 @@ -import RouteSetup -import RequestInputAccess -import RouteHandler_getAResponseHeader -import HeaderDefinition_defines -import ResponseExpr -import HeaderDefinition -import RouteSetup_getServer -import HeaderDefinition_getAHeaderName -import ServerDefinition -import RouteHandler_getAResponseExpr -import RouteSetup_getARouteHandler -import RouteHandler -import RequestExpr -import Credentials -import RouteHandler_getARequestExpr +import javascript + +query predicate test_RouteSetup(Connect::RouteSetup rs) { any() } + +query predicate test_RequestInputAccess( + HTTP::RequestInputAccess ria, string res, Connect::RouteHandler rh +) { + ria.getRouteHandler() = rh and res = ria.getKind() +} + +query predicate test_RouteHandler_getAResponseHeader( + Connect::RouteHandler rh, string name, HTTP::HeaderDefinition res +) { + res = rh.getAResponseHeader(name) +} + +query predicate test_HeaderDefinition_defines(HTTP::HeaderDefinition hd, string name, string value) { + hd.defines(name, value) and hd.getRouteHandler() instanceof Connect::RouteHandler +} + +query predicate test_ResponseExpr(HTTP::ResponseExpr e, HTTP::RouteHandler res) { + res = e.getRouteHandler() +} + +query predicate test_HeaderDefinition(HTTP::HeaderDefinition hd, Connect::RouteHandler rh) { + rh = hd.getRouteHandler() +} + +query predicate test_RouteSetup_getServer(Connect::RouteSetup rs, Expr res) { res = rs.getServer() } + +query predicate test_HeaderDefinition_getAHeaderName(HTTP::HeaderDefinition hd, string res) { + hd.getRouteHandler() instanceof Connect::RouteHandler and res = hd.getAHeaderName() +} + +query predicate test_ServerDefinition(Connect::ServerDefinition s) { any() } + +query predicate test_RouteHandler_getAResponseExpr(Connect::RouteHandler rh, HTTP::ResponseExpr res) { + res = rh.getAResponseExpr() +} + +query predicate test_RouteSetup_getARouteHandler(Connect::RouteSetup r, DataFlow::SourceNode res) { + res = r.getARouteHandler() +} + +query predicate test_RouteHandler(Connect::RouteHandler rh, Expr res) { res = rh.getServer() } + +query predicate test_RequestExpr(HTTP::RequestExpr e, HTTP::RouteHandler res) { + res = e.getRouteHandler() +} + +query predicate test_Credentials(Connect::Credentials cr, string res) { + res = cr.getCredentialsKind() +} + +query predicate test_RouteHandler_getARequestExpr(Connect::RouteHandler rh, HTTP::RequestExpr res) { + res = rh.getARequestExpr() +} From b509627113bb101bda33a2bfea6fd4cae4936b51 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 23:35:16 +0200 Subject: [PATCH 388/429] add tests for `connect` --- .../library-tests/frameworks/connect/src/test.js | 5 +++++ .../library-tests/frameworks/connect/tests.expected | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/javascript/ql/test/library-tests/frameworks/connect/src/test.js b/javascript/ql/test/library-tests/frameworks/connect/src/test.js index 3bdc40a9e9a..a310baeacde 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/src/test.js +++ b/javascript/ql/test/library-tests/frameworks/connect/src/test.js @@ -28,3 +28,8 @@ app.use(function (error, req, res, next){ app.use(function ({url, query, cookies}, res){ cookies.get(query.foobar); }); + +app.use(function (req, res){ + var url = req.url; + res.end(url); +}); diff --git a/javascript/ql/test/library-tests/frameworks/connect/tests.expected b/javascript/ql/test/library-tests/frameworks/connect/tests.expected index 474d6aaeb53..65e9bf665e3 100644 --- a/javascript/ql/test/library-tests/frameworks/connect/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/connect/tests.expected @@ -6,8 +6,10 @@ test_RouteSetup | src/test.js:19:1:20:29 | app.use ... res){}) | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | | src/test.js:28:1:30:2 | app.use ... ar);\\n}) | +| src/test.js:32:1:35:2 | app.use ... rl);\\n}) | test_RequestInputAccess | src/test.js:8:5:8:26 | req.coo ... ('foo') | cookie | src/test.js:6:9:9:1 | functio ... oo');\\n} | +| src/test.js:33:15:33:21 | req.url | url | src/test.js:32:9:35:1 | functio ... url);\\n} | test_RouteHandler_getAResponseHeader | src/test.js:6:9:9:1 | functio ... oo');\\n} | header1 | src/test.js:7:5:7:32 | res.set ... 1', '') | | src/test.js:24:9:26:1 | functio ... '');\\n} | header2 | src/test.js:25:5:25:32 | res.set ... 2', '') | @@ -23,6 +25,8 @@ test_ResponseExpr | src/test.js:24:31:24:33 | res | src/test.js:24:9:26:1 | functio ... '');\\n} | | src/test.js:25:5:25:7 | res | src/test.js:24:9:26:1 | functio ... '');\\n} | | src/test.js:28:42:28:44 | res | src/test.js:28:9:30:1 | functio ... bar);\\n} | +| src/test.js:32:24:32:26 | res | src/test.js:32:9:35:1 | functio ... url);\\n} | +| src/test.js:34:5:34:7 | res | src/test.js:32:9:35:1 | functio ... url);\\n} | test_HeaderDefinition | src/test.js:7:5:7:32 | res.set ... 1', '') | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:25:5:25:32 | res.set ... 2', '') | src/test.js:24:9:26:1 | functio ... '');\\n} | @@ -34,6 +38,7 @@ test_RouteSetup_getServer | src/test.js:19:1:20:29 | app.use ... res){}) | src/test.js:4:11:4:19 | connect() | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | src/test.js:4:11:4:19 | connect() | | src/test.js:28:1:30:2 | app.use ... ar);\\n}) | src/test.js:4:11:4:19 | connect() | +| src/test.js:32:1:35:2 | app.use ... rl);\\n}) | src/test.js:4:11:4:19 | connect() | test_HeaderDefinition_getAHeaderName | src/test.js:7:5:7:32 | res.set ... 1', '') | header1 | | src/test.js:25:5:25:32 | res.set ... 2', '') | header2 | @@ -48,6 +53,8 @@ test_RouteHandler_getAResponseExpr | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:24:31:24:33 | res | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:25:5:25:7 | res | | src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:28:42:28:44 | res | +| src/test.js:32:9:35:1 | functio ... url);\\n} | src/test.js:32:24:32:26 | res | +| src/test.js:32:9:35:1 | functio ... url);\\n} | src/test.js:34:5:34:7 | res | test_RouteSetup_getARouteHandler | src/test.js:6:1:9:2 | app.use ... o');\\n}) | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:12:1:12:42 | app.use ... word')) | src/test.js:12:9:12:41 | basicAu ... sword') | @@ -58,6 +65,7 @@ test_RouteSetup_getARouteHandler | src/test.js:19:1:20:29 | app.use ... res){}) | src/test.js:20:10:20:28 | function(req,res){} | | src/test.js:24:1:26:2 | app.use ... '');\\n}) | src/test.js:24:9:26:1 | functio ... '');\\n} | | src/test.js:28:1:30:2 | app.use ... ar);\\n}) | src/test.js:28:9:30:1 | functio ... bar);\\n} | +| src/test.js:32:1:35:2 | app.use ... rl);\\n}) | src/test.js:32:9:35:1 | functio ... url);\\n} | test_RouteHandler | src/test.js:6:9:9:1 | functio ... oo');\\n} | src/test.js:4:11:4:19 | connect() | | src/test.js:15:12:15:32 | functio ... res){} | src/test.js:4:11:4:19 | connect() | @@ -65,6 +73,7 @@ test_RouteHandler | src/test.js:20:10:20:28 | function(req,res){} | src/test.js:4:11:4:19 | connect() | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:4:11:4:19 | connect() | | src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:4:11:4:19 | connect() | +| src/test.js:32:9:35:1 | functio ... url);\\n} | src/test.js:4:11:4:19 | connect() | test_RequestExpr | src/test.js:6:27:6:29 | req | src/test.js:6:9:9:1 | functio ... oo');\\n} | | src/test.js:8:5:8:7 | req | src/test.js:6:9:9:1 | functio ... oo');\\n} | @@ -73,6 +82,8 @@ test_RequestExpr | src/test.js:20:19:20:21 | req | src/test.js:20:10:20:28 | function(req,res){} | | src/test.js:24:26:24:28 | req | src/test.js:24:9:26:1 | functio ... '');\\n} | | src/test.js:28:19:28:39 | {url, q ... ookies} | src/test.js:28:9:30:1 | functio ... bar);\\n} | +| src/test.js:32:19:32:21 | req | src/test.js:32:9:35:1 | functio ... url);\\n} | +| src/test.js:33:15:33:17 | req | src/test.js:32:9:35:1 | functio ... url);\\n} | test_Credentials | src/test.js:12:19:12:28 | 'username' | user name | | src/test.js:12:31:12:40 | 'password' | password | @@ -84,3 +95,5 @@ test_RouteHandler_getARequestExpr | src/test.js:20:10:20:28 | function(req,res){} | src/test.js:20:19:20:21 | req | | src/test.js:24:9:26:1 | functio ... '');\\n} | src/test.js:24:26:24:28 | req | | src/test.js:28:9:30:1 | functio ... bar);\\n} | src/test.js:28:19:28:39 | {url, q ... ookies} | +| src/test.js:32:9:35:1 | functio ... url);\\n} | src/test.js:32:19:32:21 | req | +| src/test.js:32:9:35:1 | functio ... url);\\n} | src/test.js:33:15:33:17 | req | From cecb6c7bddea6b584d0a608e4b6f17612eba8c02 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 23:23:06 +0200 Subject: [PATCH 389/429] add model for `live-server` --- .../javascript/frameworks/HttpFrameworks.qll | 1 + .../javascript/frameworks/LiveServer.qll | 59 +++++++++++++++++++ .../ReflectedXss/ReflectedXss.expected | 24 ++++++++ .../ReflectedXssWithCustomSanitizer.expected | 2 + .../CWE-079/ReflectedXss/live-server.js | 18 ++++++ 5 files changed, 104 insertions(+) create mode 100644 javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/live-server.js diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll index 930d2a6f5b4..7568280dcc4 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll @@ -1,6 +1,7 @@ import semmle.javascript.frameworks.Express import semmle.javascript.frameworks.Hapi import semmle.javascript.frameworks.Koa +import semmle.javascript.frameworks.LiveServer import semmle.javascript.frameworks.NodeJSLib import semmle.javascript.frameworks.Micro import semmle.javascript.frameworks.Restify diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll new file mode 100644 index 00000000000..3f1b9c13ff6 --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll @@ -0,0 +1,59 @@ +/** + * Provides classes modelling the [live-server](https://npmjs.com/package/live-server) package. + */ + +import javascript +private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared as ConnectExpressShared + +private module LiveServer { + /** + * An expression that imports the live-server package, seen as a server-definition. + */ + class ServerDefinition extends HTTP::Servers::StandardServerDefinition { + API::Node imp; + + ServerDefinition() { + imp = API::moduleImport("live-server") and + this = imp.getAnImmediateUse().asExpr() + } + + API::Node getImportNode() { result = imp } + } + + /** + * A live-server middleware definition. + * `live-server` uses the `connect` library under the hood, so the model is based on the `connect` model. + */ + class RouteHandler extends Connect::RouteHandler, DataFlow::FunctionNode { + RouteHandler() { this = any(RouteSetup setup).getARouteHandler() } + + override Parameter getRouteHandlerParameter(string kind) { + result = ConnectExpressShared::getRouteHandlerParameter(astNode, kind) + } + } + + /** + * The call to `require("live-server").start()`, seen as a route setup. + */ + class RouteSetup extends MethodCallExpr, HTTP::Servers::StandardRouteSetup { + ServerDefinition server; + API::CallNode call; + + RouteSetup() { + call = server.getImportNode().getMember("start").getACall() and + this = call.asExpr() + } + + override DataFlow::SourceNode getARouteHandler() { + exists(DataFlow::SourceNode middleware | + middleware = call.getParameter(0).getMember("middleware").getAValueReachingRhs() + | + result = middleware.getAMemberCall(["push", "unshift"]).getArgument(0).getAFunctionValue() + or + result = middleware.(DataFlow::ArrayCreationNode).getAnElement().getAFunctionValue() + ) + } + + override Expr getServer() { result = server } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected index 4e24c67c616..19805531d5b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected @@ -118,6 +118,18 @@ nodes | formatting.js:7:14:7:53 | require ... , evil) | | formatting.js:7:14:7:53 | require ... , evil) | | formatting.js:7:49:7:52 | evil | +| live-server.js:4:11:4:27 | tainted | +| live-server.js:4:21:4:27 | req.url | +| live-server.js:4:21:4:27 | req.url | +| live-server.js:6:13:6:50 | ` ... /html>` | +| live-server.js:6:13:6:50 | ` ... /html>` | +| live-server.js:6:28:6:34 | tainted | +| live-server.js:10:11:10:27 | tainted | +| live-server.js:10:21:10:27 | req.url | +| live-server.js:10:21:10:27 | req.url | +| live-server.js:12:13:12:50 | ` ... /html>` | +| live-server.js:12:13:12:50 | ` ... /html>` | +| live-server.js:12:28:12:34 | tainted | | pages/Next.jsx:8:13:8:19 | req.url | | pages/Next.jsx:8:13:8:19 | req.url | | pages/Next.jsx:8:13:8:19 | req.url | @@ -325,6 +337,16 @@ edges | formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) | | formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) | | formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) | +| live-server.js:4:11:4:27 | tainted | live-server.js:6:28:6:34 | tainted | +| live-server.js:4:21:4:27 | req.url | live-server.js:4:11:4:27 | tainted | +| live-server.js:4:21:4:27 | req.url | live-server.js:4:11:4:27 | tainted | +| live-server.js:6:28:6:34 | tainted | live-server.js:6:13:6:50 | ` ... /html>` | +| live-server.js:6:28:6:34 | tainted | live-server.js:6:13:6:50 | ` ... /html>` | +| live-server.js:10:11:10:27 | tainted | live-server.js:12:28:12:34 | tainted | +| live-server.js:10:21:10:27 | req.url | live-server.js:10:11:10:27 | tainted | +| live-server.js:10:21:10:27 | req.url | live-server.js:10:11:10:27 | tainted | +| live-server.js:12:28:12:34 | tainted | live-server.js:12:13:12:50 | ` ... /html>` | +| live-server.js:12:28:12:34 | tainted | live-server.js:12:13:12:50 | ` ... /html>` | | pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | | pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | | pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url | @@ -442,6 +464,8 @@ edges | etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value | | formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value | | formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value | +| live-server.js:6:13:6:50 | ` ... /html>` | live-server.js:4:21:4:27 | req.url | live-server.js:6:13:6:50 | ` ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value | +| live-server.js:12:13:12:50 | ` ... /html>` | live-server.js:10:21:10:27 | req.url | live-server.js:12:13:12:50 | ` ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:10:21:10:27 | req.url | user-provided value | | pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value | | pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value | | pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url | pages/api/myapi.js:2:14:2:20 | req.url | Cross-site scripting vulnerability due to $@. | pages/api/myapi.js:2:14:2:20 | req.url | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected index a1d35861d21..879f8c1e64e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected @@ -25,6 +25,8 @@ | ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value | | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value | | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value | +| live-server.js:6:13:6:50 | ` ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value | +| live-server.js:12:13:12:50 | ` ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:10:21:10:27 | req.url | user-provided value | | pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value | | pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value | | pages/api/myapi.js:2:14:2:20 | req.url | Cross-site scripting vulnerability due to $@. | pages/api/myapi.js:2:14:2:20 | req.url | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/live-server.js b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/live-server.js new file mode 100644 index 00000000000..aed560fc076 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/live-server.js @@ -0,0 +1,18 @@ +var liveServer = require("live-server"); + +const middleware = [function(req, res, next) { + const tainted = req.url; + + res.end(`${tainted}`); // NOT OK +}]; + +middleware.push(function(req, res, next) { + const tainted = req.url; + + res.end(`${tainted}`); // NOT OK +}); + +var params = { + middleware +}; +liveServer.start(params); \ No newline at end of file From 83252e5ba266e89f59ead65dfaf8c7b4f68049ca Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 30 Aug 2021 23:35:21 +0200 Subject: [PATCH 390/429] change note --- javascript/change-notes/2021-08-30-live-server.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 javascript/change-notes/2021-08-30-live-server.md diff --git a/javascript/change-notes/2021-08-30-live-server.md b/javascript/change-notes/2021-08-30-live-server.md new file mode 100644 index 00000000000..4518dad451e --- /dev/null +++ b/javascript/change-notes/2021-08-30-live-server.md @@ -0,0 +1,6 @@ +lgtm,codescanning +* The dataflow libraries now model sources and sinks from the `live-server` library. + The model for `connect` has improved to recognize more sources and sinks. + Affected packages are + [live-server](https://www.npmjs.com/package/live-server), + [connect](https://www.npmjs.com/package/connect) \ No newline at end of file From 28dce6e95a92e227584aa59287c54c62be04bffc Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 31 Aug 2021 14:21:46 +0200 Subject: [PATCH 391/429] fix non-monotonic recursion in `js/missing-rate-limiting` --- .../javascript/security/dataflow/MissingRateLimiting.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll index b9cb1b5059a..a651883165d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll @@ -29,7 +29,7 @@ private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpress /** * A route handler that should be rate-limited. */ -abstract class ExpensiveRouteHandler extends HTTP::RouteHandler { +abstract class ExpensiveRouteHandler extends DataFlow::Node { Express::RouteHandler impl; ExpensiveRouteHandler() { this = impl } @@ -42,10 +42,6 @@ abstract class ExpensiveRouteHandler extends HTTP::RouteHandler { * `referenceLabel` are ignored and should be bound to dummy values. */ abstract predicate explain(string explanation, DataFlow::Node reference, string referenceLabel); - - override HTTP::HeaderDefinition getAResponseHeader(string name) { - result = impl.getAResponseHeader(name) - } } /** From 0ba334bb2247aa6716128b6f1fc96c9038e6e70d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 31 Aug 2021 14:26:36 +0200 Subject: [PATCH 392/429] C#: Temporarily extract modified pointers as unmodified during CIL extraction --- .../Semmle.Extraction.CIL/Entities/PointerType.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs index 1a6bd474bd0..9ce05b4a054 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PointerType.cs @@ -11,6 +11,14 @@ namespace Semmle.Extraction.CIL.Entities public PointerType(Context cx, Type pointee) : base(cx) { this.pointee = pointee; + + if (pointee is ModifiedType mt) + { + cx.Extractor.Logger.Log( + Util.Logging.Severity.Info, + $"Pointer to modified type {pointee.GetQualifiedName()} is changed to {mt.Unmodified.GetQualifiedName()}"); + this.pointee = mt.Unmodified; + } } public override bool Equals(object? obj) From d6ae19c87d050b39de642b3a0f7baf8387a11e1b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 31 Aug 2021 14:29:53 +0200 Subject: [PATCH 393/429] C#: Handle non-critical exception in CIL local variable extraction --- .../Entities/DefinitionMethod.cs | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs index 5c48e5e52e1..073527a523b 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/DefinitionMethod.cs @@ -114,25 +114,39 @@ namespace Semmle.Extraction.CIL.Entities if (!body.LocalSignature.IsNil) { - var locals = Context.MdReader.GetStandaloneSignature(body.LocalSignature); - var localVariableTypes = locals.DecodeLocalSignature(Context.TypeSignatureDecoder, this); - - this.locals = new LocalVariable[localVariableTypes.Length]; - - for (var l = 0; l < this.locals.Length; ++l) + var localVariableTypes = System.Collections.Immutable.ImmutableArray.Empty; + var hasError = false; + try { - var t = localVariableTypes[l]; - if (t is ByRefType brt) + var locals = Context.MdReader.GetStandaloneSignature(body.LocalSignature); + localVariableTypes = locals.DecodeLocalSignature(Context.TypeSignatureDecoder, this); + } + catch (System.BadImageFormatException exc) + { + Context.Extractor.Logger.Log(Util.Logging.Severity.Info, + $"Could not decode locals in method {declaringType.GetQualifiedName()}.{name}. {exc}"); + hasError = true; + } + + if (!hasError) + { + this.locals = new LocalVariable[localVariableTypes.Length]; + + for (var l = 0; l < this.locals.Length; ++l) { - t = brt.ElementType; - this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t)); - yield return this.locals[l]; - yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref); - } - else - { - this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t)); - yield return this.locals[l]; + var t = localVariableTypes[l]; + if (t is ByRefType brt) + { + t = brt.ElementType; + this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t)); + yield return this.locals[l]; + yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref); + } + else + { + this.locals[l] = Context.Populate(new LocalVariable(Context, Implementation, l, t)); + yield return this.locals[l]; + } } } } From b267d26ff8fad03ea123669ba4a95670a89c5238 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 31 Aug 2021 14:34:27 +0200 Subject: [PATCH 394/429] C#: Fix completely broken type argument extraction in NoMetadataHandleType --- .../Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs | 2 +- csharp/extractor/Semmle.Util/StringExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs index 999259e9ad6..11420a8adcc 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/NoMetadataHandleType.FullyQualifiedNameParser.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CIL.Entities // "T3,[T4, Assembly1, Version=...],T5,T6" string typeArgs; - (name, _, typeArgs, _) = name.Split(firstBracketIndex, firstBracketIndex + 1, lastBracketIndex - firstBracketIndex - 1); + (name, _, typeArgs, _) = name.Split(firstBracketIndex, firstBracketIndex + 1, lastBracketIndex); var thisTypeArgCount = GenericsHelper.GetGenericTypeParameterCount(name); if (thisTypeArgCount == 0) diff --git a/csharp/extractor/Semmle.Util/StringExtensions.cs b/csharp/extractor/Semmle.Util/StringExtensions.cs index d5d6c8cf27d..e56f106fe1f 100644 --- a/csharp/extractor/Semmle.Util/StringExtensions.cs +++ b/csharp/extractor/Semmle.Util/StringExtensions.cs @@ -20,7 +20,7 @@ namespace Semmle.Util 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]); + return (split[0], split[1], split[2], split[3]); } private static List Split(this string self, params int[] indices) From b38a23daeea35bc58c69c479832702db2a7702aa Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 15:12:47 +0100 Subject: [PATCH 395/429] Fix test cases featuring primitive arrays Previously we couldn't print the name of types like `byte[]` for example. --- java/ql/src/utils/FlowTestCase.qll | 2 +- java/ql/src/utils/FlowTestCaseUtils.qll | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/src/utils/FlowTestCase.qll b/java/ql/src/utils/FlowTestCase.qll index 33459ed790c..5bf5517f4e5 100644 --- a/java/ql/src/utils/FlowTestCase.qll +++ b/java/ql/src/utils/FlowTestCase.qll @@ -44,7 +44,7 @@ private class CallableToTest extends Callable { summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _) and this = interpretElement(namespace, type, subtypes, name, signature, ext) and this.isPublic() and - getRootType(this.getDeclaringType()).isPublic() + getRootType(this.getDeclaringType()).(RefType).isPublic() ) } } diff --git a/java/ql/src/utils/FlowTestCaseUtils.qll b/java/ql/src/utils/FlowTestCaseUtils.qll index 3456678bd16..8a48272a2ae 100644 --- a/java/ql/src/utils/FlowTestCaseUtils.qll +++ b/java/ql/src/utils/FlowTestCaseUtils.qll @@ -12,7 +12,7 @@ private import FlowTestCase */ Type getRootSourceDeclaration(Type t) { if t instanceof RefType - then result = getRootType(replaceTypeVariable(t)).getSourceDeclaration() + then result = getRootType(replaceTypeVariable(t)).(RefType).getSourceDeclaration() else result = t } @@ -77,7 +77,7 @@ predicate mayBeAmbiguous(Callable c) { /** * Returns the outermost type enclosing type `t` (which may be `t` itself). */ -RefType getRootType(RefType t) { +Type getRootType(Type t) { if t instanceof NestedType then result = getRootType(t.(NestedType).getEnclosingType()) else @@ -95,9 +95,9 @@ string getShortNameIfPossible(Type t) { if t instanceof Array then result = getShortNameIfPossible(t.(Array).getComponentType()) + "[]" else ( - getRootSourceDeclaration(t) = any(TestCase tc).getADesiredImport() and if t instanceof RefType then + getRootSourceDeclaration(t) = any(TestCase tc).getADesiredImport() and exists(RefType replaced, string nestedName | replaced = replaceTypeVariable(t).getSourceDeclaration() and nestedName = replaced.nestedName().replaceAll("$", ".") From 7977d9c253a978dcb6ad0ce60770fc846304a4f2 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 15:26:09 +0100 Subject: [PATCH 396/429] Fix minor mistakes in old Guava models Also add tests for the affected functions --- .../semmle/code/java/frameworks/guava/Base.qll | 2 +- .../lib/semmle/code/java/frameworks/guava/IO.qll | 2 +- .../library-tests/frameworks/guava/TestBase.java | 2 +- .../library-tests/frameworks/guava/TestIO.java | 15 +++++++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/guava/Base.qll b/java/ql/lib/semmle/code/java/frameworks/guava/Base.qll index 2e5e37a9bfb..c35da02815e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/guava/Base.qll +++ b/java/ql/lib/semmle/code/java/frameworks/guava/Base.qll @@ -62,7 +62,7 @@ private class GuavaBaseCsv extends SummaryModelCsv { "com.google.common.base;Converter;true;apply;(Object);;Argument[0];ReturnValue;taint", "com.google.common.base;Converter;true;convert;(Object);;Argument[0];ReturnValue;taint", "com.google.common.base;Converter;true;convertAll;(Iterable);;Element of Argument[0];Element of ReturnValue;taint", - "com.google.common.base;Supplier;true;get;();;Argument[0];ReturnValue;taint", + "com.google.common.base;Supplier;true;get;();;Argument[-1];ReturnValue;taint", "com.google.common.base;Suppliers;false;ofInstance;(Object);;Argument[0];ReturnValue;taint", "com.google.common.base;Suppliers;false;memoize;(Supplier);;Argument[0];ReturnValue;taint", "com.google.common.base;Suppliers;false;memoizeWithExpiration;(Supplier,long,TimeUnit);;Argument[0];ReturnValue;taint", diff --git a/java/ql/lib/semmle/code/java/frameworks/guava/IO.qll b/java/ql/lib/semmle/code/java/frameworks/guava/IO.qll index 60720a941ca..b87d93b19c1 100644 --- a/java/ql/lib/semmle/code/java/frameworks/guava/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/guava/IO.qll @@ -34,7 +34,7 @@ private class GuavaIoCsv extends SummaryModelCsv { "com.google.common.io;ByteSource;true;slice;(long,long);;Argument[-1];ReturnValue;taint", "com.google.common.io;ByteSource;true;wrap;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", - "com.google.common.io;ByteStreams;false;copy;(ReadablyByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint", + "com.google.common.io;ByteStreams;false;copy;(ReadableByteChannel,WritableByteChannel);;Argument[0];Argument[1];taint", "com.google.common.io;ByteStreams;false;limit;(InputStream,long);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(byte[]);;Argument[0];ReturnValue;taint", "com.google.common.io;ByteStreams;false;newDataInput;(byte[],int);;Argument[0];ReturnValue;taint", diff --git a/java/ql/test/library-tests/frameworks/guava/TestBase.java b/java/ql/test/library-tests/frameworks/guava/TestBase.java index 6fd6e4d910a..963b971235f 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestBase.java +++ b/java/ql/test/library-tests/frameworks/guava/TestBase.java @@ -75,7 +75,7 @@ class TestBase { } void test6() { - sink(Suppliers.memoize(Suppliers.memoizeWithExpiration(Suppliers.synchronizedSupplier(Suppliers.ofInstance(taint())), 3, TimeUnit.HOURS))); // $numTaintFlow=1 + sink(Suppliers.memoize(Suppliers.memoizeWithExpiration(Suppliers.synchronizedSupplier(Suppliers.ofInstance(taint())), 3, TimeUnit.HOURS)).get()); // $numTaintFlow=1 } void test7() { diff --git a/java/ql/test/library-tests/frameworks/guava/TestIO.java b/java/ql/test/library-tests/frameworks/guava/TestIO.java index 9871b49ac0f..8d07256fd9f 100644 --- a/java/ql/test/library-tests/frameworks/guava/TestIO.java +++ b/java/ql/test/library-tests/frameworks/guava/TestIO.java @@ -8,7 +8,11 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.Closeable; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.nio.file.Path; +import java.nio.file.Paths; import java.io.IOException; class TestIO { @@ -16,6 +20,7 @@ class TestIO { String staint(){ return (String) taint(); } byte[] btaint() { return (byte[]) taint(); } InputStream itaint() { return (InputStream) taint(); } + ReadableByteChannel rbctaint() { return (ReadableByteChannel) taint(); } Reader rtaint() { return new InputStreamReader(itaint()); } Path ptaint() { return (Path) taint(); } @@ -75,6 +80,16 @@ class TestIO { } void test3() throws IOException { + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteStreams.copy(itaint(), out); + sink(out); // $numTaintFlow=1 + } + { + WritableByteChannel out = FileChannel.open(Paths.get("/tmp/xyz")); + ByteStreams.copy(rbctaint(), out); + sink(out); // $numTaintFlow=1 + } sink(ByteStreams.limit(itaint(), 1337)); // $numTaintFlow=1 sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 sink(ByteStreams.newDataInput(btaint(), 0)); // $numTaintFlow=1 From a47efc43486f46276343d672fa92183a85bc0a2d Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 31 Aug 2021 19:18:03 +0100 Subject: [PATCH 397/429] Expression docs: mention multiple sort criteria --- docs/codeql/ql-language-reference/expressions.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/codeql/ql-language-reference/expressions.rst b/docs/codeql/ql-language-reference/expressions.rst index 08a925b50b8..927eb6def53 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -201,9 +201,10 @@ based on the `Unicode value `` with the keywords ``order by``, then -the expression that specifies the order, and optionally the keyword ``asc`` or ``desc`` +one or more comma-separated expressions that specifies the order, and optionally the keyword ``asc`` or ``desc`` after each expression (to determine whether to order the expression in ascending or descending order). If you don't -specify an ordering, it defaults to ``asc``. +specify an ordering, it defaults to ``asc``. For example, ``order by o.getName() asc, o.getSize() desc`` +might be used to order some object by name, breaking ties by descending size. The following aggregates are available in QL: @@ -229,11 +230,11 @@ The following aggregates are available in QL: In this case, ```` must be of numeric type or of type ``string``. For example, the following aggregation returns the name of the ``.js`` file (or files) with the - largest number of lines: + largest number of lines, using the number of lines of code to break ties: .. code-block:: ql - max(File f | f.getExtension() = "js" | f.getBaseName() order by f.getTotalNumberOfLines()) + max(File f | f.getExtension() = "js" | f.getBaseName() order by f.getTotalNumberOfLines(), f.getNumberOfLinesOfCode()) The following aggregation returns the minimum string ``s`` out of the three strings mentioned below, that is, the string that comes first in the lexicographic ordering of all the possible From 0923d1fdc197c8ae3205d153e3d75fece374d20b Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 31 Aug 2021 13:39:04 -0700 Subject: [PATCH 398/429] Docs: Update documentation for query suites Adds some clarification around the `qlpack` directive. The semantics has changed. This provides a new example and some description. --- .../creating-codeql-query-suites.rst | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index ba164a40da0..39b99e224d4 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -4,8 +4,8 @@ Creating CodeQL query suites ============================ CodeQL query suites provide a way of selecting queries, based on their -filename, location on disk or in a QL pack, or metadata properties. -Create query suites for the queries that you want to frequently use in +filename, location on disk or in a QL pack, or metadata properties. +Create query suites for the queries that you want to frequently use in your CodeQL analyses. Query suites allow you to pass multiple queries to @@ -19,7 +19,7 @@ suite definition have been executed, the result is a set of selected queries. .. pull-quote:: Note Any custom queries that you want to add to a query suite must be in a :doc:`QL - pack ` 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 `." @@ -50,10 +50,15 @@ queries using: - queries: from: -- A ``qlpack`` instruction---tells CodeQL to look for queries in a named QL pack:: +- A ``qlpack`` instruction---tells CodeQL to resolve queries in the default suite of the + named QL pack:: - qlpack: + The default suite of a query pack includes all of the common and recommended queries + inside of that suite. Not all query packs have a default suite. Those that do not + define a default suite will resolve all of the queries in all of their subdirectories. + .. pull-quote:: Note When pathnames appear in query suite definitions, they must always @@ -73,7 +78,7 @@ Filtering the queries in a query suite After you have defined the initial set of queries to add to your suite by specifying ``query``, ``queries``, or ``qlpack`` instructions, you can add ``include`` and ``exclude`` instructions. These instructions define selection -criteria based on specific properties: +criteria based on specific properties: - When you execute an ``include`` instruction on a set of queries, any queries that match your conditions are retained in the selection, and queries @@ -99,12 +104,12 @@ For both instructions, the argument is a constraint block---that is, a YAML map representing the constraints. Each constraint is a map entry, where the key is typically a query metadata property. The value can be: -- A single string. +- A single string. - A ``/``\ -enclosed `regular expression `__. - A list containing strings, regular expressions, or both. To match a constraint, a metadata value must match one of the strings or -regular expressions. When there is more than one metadata key, each key must be matched. +regular expressions. When there is more than one metadata key, each key must be matched. For more information about query metadata properties, see ":ref:`Metadata for CodeQL queries `." @@ -112,7 +117,7 @@ In addition to metadata tags, the keys in the constraint block can also be: - ``query filename``---matches on the last path component of the query file name. - ``query path``---matches on the path to the query file relative to its - enclosing QL pack. + enclosing QL pack. - ``tags contain``---one of the given match strings must match one of the space-separated components of the value of the ``@tags`` metadata property. - ``tags contain all``---each of the given match strings must match one of the @@ -121,6 +126,14 @@ In addition to metadata tags, the keys in the constraint block can also be: Examples ~~~~~~~~ +To define a suite that selects all queries in the default suite of the +``codeql/cpp-queries`` QL pack, and then refines them to only include +security queries, use:: + + - queries: codeql/cpp-queries + - include: + tags contain: security + To define a suite that selects all queries with ``@kind problem`` and ``@precision high`` from the ``my-custom-queries`` directory, use:: @@ -136,34 +149,35 @@ recommendation``, use:: - queries: my-custom-queries - include: kind: problem - - exclude: + - exclude: problem.severity: recommendation To create a suite that selects all queries with ``@tag security`` and -``@problem.severity high`` or ``very-high`` from the ``codeql-cpp`` QL pack, +``@problem.severity high`` or ``very-high`` from the ``codeql/cpp-queries`` QL pack, use:: - - qlpack: codeql-cpp - - include: + - queries: . + from: codeql/cpp-queries + - include: tags contain: security - problem.severity: + problem.severity: - high - very-high Reusing existing query suite definitions ----------------------------------------- -Existing query suite definitions can be reused by specifying: +Existing query suite definitions can be reused by specifying: - An ``import`` instruction---adds the queries selected by a previously defined ``.qls`` file to the current suite:: - + - import: The path to the imported suite must be relative to the QL pack containing the current suite definition. If the imported query suite is in a different QL pack you can use:: - + - import: from: @@ -175,12 +189,12 @@ Existing query suite definitions can be reused by specifying: applied ``.qls`` file are executed as if they appear in place of ``apply``. Any ``include`` and ``exclude`` instructions from the applied suite also act on queries added by any earlier instructions:: - + - apply: The ``apply`` instruction can also be used to apply a set of reusable conditions, saved in a ``.yml`` file, to multiple query definitions. For more - information, see the `example <#example>`__ below. + information, see the `example <#example>`__ below. - An ``eval`` instruction---performs the same function as an ``import`` instruction, but takes a full suite definition as the argument, rather than the @@ -236,7 +250,7 @@ instruction:: This value is displayed when you run `codeql resolve queries <../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>`__." +<#specifying-well-known-query-suites>`__." Saving a query suite -------------------- @@ -248,8 +262,8 @@ Specifying well-known query suites ---------------------------------- You can use QL packs to declare directories that contain "well-known" query -suites. You can use "well-known" query suites on the command line by referring -to their file name, +suites. You can use "well-known" query suites on the command line by referring +to their file name, 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 @@ -263,7 +277,7 @@ You can specify query suites on the command line for any command that accepts ``.qls`` files. For example, you can compile the queries selected by a suite definition using ``query compile``, or use the queries in an analysis using ``database analyze``. For more information about analyzing CodeQL databases, see -":doc:`Analyzing databases with the CodeQL CLI `." +":doc:`Analyzing databases with the CodeQL CLI `." Viewing the query suites used on LGTM.com ----------------------------------------- From 21c168e229cc4de28ec6f524129e2fd89782dc56 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Tue, 31 Aug 2021 14:47:28 -0700 Subject: [PATCH 399/429] Apply suggestions from code review Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com> --- docs/codeql/codeql-cli/creating-codeql-query-suites.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 39b99e224d4..ceaa104f4d0 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -55,9 +55,9 @@ queries using: - qlpack: - The default suite of a query pack includes all of the common and recommended queries - inside of that suite. Not all query packs have a default suite. Those that do not - define a default suite will resolve all of the queries in all of their subdirectories. + The default suite of a query pack includes a recommended set of queries + inside of that query pack. Not all query packs have a default suite. If the given query pack does not + define a default suite, the `qlpack` instruction will resolve to all of the queries within the pack. .. pull-quote:: Note @@ -130,7 +130,7 @@ To define a suite that selects all queries in the default suite of the ``codeql/cpp-queries`` QL pack, and then refines them to only include security queries, use:: - - queries: codeql/cpp-queries + - qlpack: codeql/cpp-queries - include: tags contain: security From 98d018ce26f98f6ad4f2c29454797d542e2c8f3f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 10:09:40 +0200 Subject: [PATCH 400/429] remove redundant extends clause Co-authored-by: Esben Sparre Andreasen --- javascript/ql/lib/semmle/javascript/frameworks/Connect.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll index e9829bd78e5..c835f7eb84d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll @@ -24,7 +24,7 @@ module Connect { * but support for other kinds of route handlers can be added by implementing * additional subclasses of this class. */ - abstract class RouteHandler extends HTTP::Servers::StandardRouteHandler, NodeJSLib::RouteHandler, + abstract class RouteHandler extends NodeJSLib::RouteHandler, DataFlow::ValueNode { /** * Gets the parameter of kind `kind` of this route handler. From f8d46677b91182760d4ca90960377d9f5e03c40b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 10:11:05 +0200 Subject: [PATCH 401/429] add RequestExpr as an alias to NodeJSLib::RequestExpr in Connect.qll --- javascript/ql/lib/semmle/javascript/frameworks/Connect.qll | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll index c835f7eb84d..06138746fa6 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll @@ -24,8 +24,7 @@ module Connect { * but support for other kinds of route handlers can be added by implementing * additional subclasses of this class. */ - abstract class RouteHandler extends NodeJSLib::RouteHandler, - DataFlow::ValueNode { + abstract class RouteHandler extends NodeJSLib::RouteHandler, DataFlow::ValueNode { /** * Gets the parameter of kind `kind` of this route handler. * @@ -109,11 +108,13 @@ module Connect { override string getCredentialsKind() { result = kind } } + class RequestExpr = NodeJSLib::RequestExpr; + /** * An access to a user-controlled Connect request input. */ private class RequestInputAccess extends HTTP::RequestInputAccess { - NodeJSLib::RequestExpr request; + RequestExpr request; string kind; RequestInputAccess() { From 303e02fb8adc31d5d9bae43bc7ec743cb291741e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 1 Sep 2021 10:45:47 +0100 Subject: [PATCH 402/429] Fix typo Co-authored-by: Marcono1234 --- 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 927eb6def53..1bf39dda6ba 100644 --- a/docs/codeql/ql-language-reference/expressions.rst +++ b/docs/codeql/ql-language-reference/expressions.rst @@ -201,7 +201,7 @@ based on the `Unicode value `` with the keywords ``order by``, then -one or more comma-separated expressions that specifies the order, and optionally the keyword ``asc`` or ``desc`` after each expression +one or more comma-separated expressions that specify the order, and optionally the keyword ``asc`` or ``desc`` after each expression (to determine whether to order the expression in ascending or descending order). If you don't specify an ordering, it defaults to ``asc``. For example, ``order by o.getName() asc, o.getSize() desc`` might be used to order some object by name, breaking ties by descending size. From 75a3f34e86e08ec44aa3554582a4d849f9957e6a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 12:44:02 +0200 Subject: [PATCH 403/429] use if-else in `ReDoSUtil::getCanonicalizationFlags` Co-authored-by: Esben Sparre Andreasen --- .../semmle/javascript/security/performance/ReDoSUtil.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index cdd42ce1540..845276204a7 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -187,11 +187,10 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { string getCanonicalizationFlags(RegExpTerm root) { root.isRootTerm() and ( - RegExpFlags::isIgnoreCase(root) and - result = "i" - or - not RegExpFlags::isIgnoreCase(root) and - result = "" + if RegExpFlags::isIgnoreCase(root) then + result = "i" + else + result = "" ) } From ff74fe1e03e70e092122e679d45bdceeff39fb8f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 12:45:20 +0200 Subject: [PATCH 404/429] rename hasChildThatMatchesIgnoringCasing to hasChildThatMatchesIgnoringCasingFlags --- .../javascript/security/performance/ReDoSUtil.qll | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 845276204a7..0fdeccc05b2 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -186,12 +186,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { */ string getCanonicalizationFlags(RegExpTerm root) { root.isRootTerm() and - ( - if RegExpFlags::isIgnoreCase(root) then - result = "i" - else - result = "" - ) + (if RegExpFlags::isIgnoreCase(root) then result = "i" else result = "") } /** @@ -324,16 +319,16 @@ private module CharacterClasses { if RegExpFlags::isIgnoreCase(cc.getRootTerm()) then // normalize everything to lower case if the regexp is case insensitive - exists(string c | hasChildThatMatchesIgnoringCasing(cc, c) | char = c.toLowerCase()) - else hasChildThatMatchesIgnoringCasing(cc, char) + exists(string c | hasChildThatMatchesIgnoringCasingFlags(cc, c) | char = c.toLowerCase()) + else hasChildThatMatchesIgnoringCasingFlags(cc, char) } /** * Holds if the character class `cc` has a child (constant or range) that matches `char`. - * Ignores whether the character class is inside a regular expression that ignores casing. + * Ignores whether the character class is inside a regular expression that has the ignore case flag. */ pragma[noinline] - predicate hasChildThatMatchesIgnoringCasing(RegExpCharacterClass cc, string char) { + predicate hasChildThatMatchesIgnoringCasingFlags(RegExpCharacterClass cc, string char) { exists(getCanonicalCharClass(cc)) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() From 537450606e929a7d2d643d0e0defb1a384c87c8b Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 12:46:50 +0200 Subject: [PATCH 405/429] use a consistent comment about the ignore case flag --- .../lib/semmle/javascript/security/performance/ReDoSUtil.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 0fdeccc05b2..302510a1c55 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -201,7 +201,7 @@ private newtype TInputSymbol = not RegExpFlags::isIgnoreCase(cc.getRootTerm()) ).getValue().charAt(_) or - // normalize to lower case if the regexp is case insensitive + // normalize everything to lower case if the regexp is case insensitive c = any(RegexpCharacterConstant cc, string char | cc instanceof RelevantRegExpTerm and @@ -577,7 +577,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { not RegExpFlags::isIgnoreCase(s.getRootTerm()) and lbl = Char(s.getValue().charAt(i)) or - // normalizing to lower case if ignorecase flag is set + // normalize everything to lower case if the regexp is case insensitive RegExpFlags::isIgnoreCase(s.getRootTerm()) and exists(string c | c = s.getValue().charAt(i) | lbl = Char(c.toLowerCase())) ) and From a3289fabe196e17900339045d97fb933c1169ff9 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 1 Sep 2021 12:47:06 +0200 Subject: [PATCH 406/429] sync ReDoSUtil with python --- .../python/security/performance/ReDoSUtil.qll | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index cdd42ce1540..302510a1c55 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -186,13 +186,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { */ string getCanonicalizationFlags(RegExpTerm root) { root.isRootTerm() and - ( - RegExpFlags::isIgnoreCase(root) and - result = "i" - or - not RegExpFlags::isIgnoreCase(root) and - result = "" - ) + (if RegExpFlags::isIgnoreCase(root) then result = "i" else result = "") } /** @@ -207,7 +201,7 @@ private newtype TInputSymbol = not RegExpFlags::isIgnoreCase(cc.getRootTerm()) ).getValue().charAt(_) or - // normalize to lower case if the regexp is case insensitive + // normalize everything to lower case if the regexp is case insensitive c = any(RegexpCharacterConstant cc, string char | cc instanceof RelevantRegExpTerm and @@ -325,16 +319,16 @@ private module CharacterClasses { if RegExpFlags::isIgnoreCase(cc.getRootTerm()) then // normalize everything to lower case if the regexp is case insensitive - exists(string c | hasChildThatMatchesIgnoringCasing(cc, c) | char = c.toLowerCase()) - else hasChildThatMatchesIgnoringCasing(cc, char) + exists(string c | hasChildThatMatchesIgnoringCasingFlags(cc, c) | char = c.toLowerCase()) + else hasChildThatMatchesIgnoringCasingFlags(cc, char) } /** * Holds if the character class `cc` has a child (constant or range) that matches `char`. - * Ignores whether the character class is inside a regular expression that ignores casing. + * Ignores whether the character class is inside a regular expression that has the ignore case flag. */ pragma[noinline] - predicate hasChildThatMatchesIgnoringCasing(RegExpCharacterClass cc, string char) { + predicate hasChildThatMatchesIgnoringCasingFlags(RegExpCharacterClass cc, string char) { exists(getCanonicalCharClass(cc)) and exists(RegExpTerm child | child = cc.getAChild() | char = child.(RegexpCharacterConstant).getValue() @@ -583,7 +577,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { not RegExpFlags::isIgnoreCase(s.getRootTerm()) and lbl = Char(s.getValue().charAt(i)) or - // normalizing to lower case if ignorecase flag is set + // normalize everything to lower case if the regexp is case insensitive RegExpFlags::isIgnoreCase(s.getRootTerm()) and exists(string c | c = s.getValue().charAt(i) | lbl = Char(c.toLowerCase())) ) and From ffd2a388a982c224aa11cb2a489b0a953fe1eb6e Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Wed, 1 Sep 2021 15:30:33 +0200 Subject: [PATCH 407/429] Update qldoc for the Access class The access class does not capture function accesses that are part of a function call expression. This updates makes that explicit --- cpp/ql/lib/semmle/code/cpp/exprs/Access.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll index 681fb41fa67..2c491d63487 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll @@ -9,7 +9,7 @@ import semmle.code.cpp.Enum private import semmle.code.cpp.dataflow.EscapesTree /** - * A C/C++ access expression. This refers to a function, variable, or enum constant. + * A C/C++ access expression. This refers to a function (excluding function references in function call expressions), variable, or enum constant. */ class Access extends Expr, NameQualifiableElement, @access { // As `@access` is a union type containing `@routineexpr` (which describes function accesses From 7310590f90aa1fea6463ea477648a638296efca1 Mon Sep 17 00:00:00 2001 From: Remco Vermeulen Date: Wed, 1 Sep 2021 15:36:00 +0200 Subject: [PATCH 408/429] Update qldoc FunctionAccess class The `FunctionAccess` class doesn't capture accesses of functions in function call expressions. This update makes that explicit. --- cpp/ql/lib/semmle/code/cpp/exprs/Access.qll | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll index 2c491d63487..e18c0c78dc6 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll @@ -350,6 +350,15 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess { * int (*myFunctionPointer)(int) = &myFunctionTarget; * } * ``` + * This excludes function accesses in function call expressions. + * For example the access `myFunctionTarget` in `myFunction` in the following code: + * ``` + * int myFunctionTarget(int); + * + * void myFunction() { + * myFunctionTarget(1); + * } + * ``` */ class FunctionAccess extends Access, @routineexpr { FunctionAccess() { not iscall(underlyingElement(this), _) } From df04c5044c085463065f1335fa266289bd2bb44f Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 2 Sep 2021 08:54:39 +0200 Subject: [PATCH 409/429] use `concat` instead of `strictconcat` in RegexTreeView.qll --- python/ql/lib/semmle/python/RegexTreeView.qll | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/python/ql/lib/semmle/python/RegexTreeView.qll b/python/ql/lib/semmle/python/RegexTreeView.qll index 784ea06ca29..9784e057402 100644 --- a/python/ql/lib/semmle/python/RegexTreeView.qll +++ b/python/ql/lib/semmle/python/RegexTreeView.qll @@ -63,11 +63,7 @@ class RegExpLiteral extends TRegExpLiteral, RegExpParent { predicate isIgnoreCase() { re.getAMode() = "IGNORECASE" } - string getFlags() { - not exists(re.getAMode()) and result = "" - or - result = strictconcat(string mode | mode = re.getAMode() | mode, " | ") - } + string getFlags() { result = concat(string mode | mode = re.getAMode() | mode, " | ") } override Regex getRegex() { result = re } From 1ad204d89e0786d252402bc863c2412ca21c9d17 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 2 Sep 2021 09:15:43 +0200 Subject: [PATCH 410/429] make after and TState private in ReDoSUtil --- .../lib/semmle/javascript/security/performance/ReDoSUtil.qll | 4 ++-- .../ql/lib/semmle/python/security/performance/ReDoSUtil.qll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll index 302510a1c55..65431d7179e 100644 --- a/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll +++ b/javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll @@ -544,7 +544,7 @@ private State before(RegExpTerm t) { result = Match(t, 0) } /** * Gets a state the NFA may be in after matching `t`. */ -State after(RegExpTerm 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) | @@ -673,7 +673,7 @@ RegExpRoot getRoot(RegExpTerm term) { /** * A state in the NFA. */ -newtype TState = +private newtype TState = /** * A state representing that the NFA is about to match a term. * `i` is used to index into multi-char literals. diff --git a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll index 302510a1c55..65431d7179e 100644 --- a/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll +++ b/python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll @@ -544,7 +544,7 @@ private State before(RegExpTerm t) { result = Match(t, 0) } /** * Gets a state the NFA may be in after matching `t`. */ -State after(RegExpTerm 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) | @@ -673,7 +673,7 @@ RegExpRoot getRoot(RegExpTerm term) { /** * A state in the NFA. */ -newtype TState = +private newtype TState = /** * A state representing that the NFA is about to match a term. * `i` is used to index into multi-char literals. From 9c4a50503c3cca0d1ffa774b76d3aeed8738ec51 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 19 Aug 2021 16:03:39 +0100 Subject: [PATCH 411/429] Allow local interfaces Java 16 permits enums and interfaces to be declared method-locally. Enums are already classes, but interfaces are not (in dbscheme terms), so we need to permit isLocalClass to tag them like it already does classes. --- java/ql/lib/config/semmlecode.dbscheme | 2 +- .../old.dbscheme | 987 ++++++++++++++++++ .../semmlecode.dbscheme | 987 ++++++++++++++++++ .../upgrade.properties | 2 + 4 files changed, 1977 insertions(+), 1 deletion(-) create mode 100755 java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/old.dbscheme create mode 100755 java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme create mode 100644 java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index b4e689c9042..0572efbc095 100755 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -442,7 +442,7 @@ isAnonymClass( #keyset[classid] #keyset[parent] isLocalClass( - int classid: @class ref, + int classid: @classorinterface ref, int parent: @localclassdeclstmt ref ); diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/old.dbscheme b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/old.dbscheme new file mode 100755 index 00000000000..b4e689c9042 --- /dev/null +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/old.dbscheme @@ -0,0 +1,987 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + 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 + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#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( + unique 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 +); + +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 +); + +/* + * External artifacts + */ + +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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +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 +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +isRecord( + unique int id: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @class ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme new file mode 100755 index 00000000000..0572efbc095 --- /dev/null +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme @@ -0,0 +1,987 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + 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 + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#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( + unique 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 +); + +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 +); + +/* + * External artifacts + */ + +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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +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 +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +isRecord( + unique int id: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @classorinterface ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties new file mode 100644 index 00000000000..54f153b7c7f --- /dev/null +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties @@ -0,0 +1,2 @@ +description: Java 16: allow static interfaces +compatibility: backwards From ca5c2b2acf12e30c2862c6d8b5b9920b9b94fc37 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 23 Aug 2021 10:46:54 +0100 Subject: [PATCH 412/429] Fix description wording Co-authored-by: Marcono1234 --- .../b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties index 54f153b7c7f..1cff2f6073f 100644 --- a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties @@ -1,2 +1,2 @@ -description: Java 16: allow static interfaces +description: Java 16: allow local interfaces compatibility: backwards From e048a729db326c19cf8a1e98b414825a381bc34c Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 23 Aug 2021 19:01:32 +0100 Subject: [PATCH 413/429] Add Interface.isLocal and use it where appropriate Some EJB logic regrettably needs to be renamed out of the way. Hopefully the churn caused by this is less than would be caused if Interface's isLocal needed to be named differently from Class.isLocal. --- java/ql/lib/semmle/code/java/Member.qll | 2 +- java/ql/lib/semmle/code/java/Statement.qll | 14 +++-- java/ql/lib/semmle/code/java/Type.qll | 62 +++++++++---------- .../code/java/frameworks/javaee/ejb/EJB.qll | 14 ++--- java/ql/src/DeadCode/FLinesOfDeadCode.ql | 2 +- java/ql/src/utils/Stubs.qll | 9 +-- 6 files changed, 52 insertions(+), 51 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 94dfdc9b3cc..50d8e2f0310 100755 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -45,7 +45,7 @@ class Member extends Element, Annotatable, Modifiable, @member { Callable getEnclosingCallable() { exists(NestedClass nc | this.getDeclaringType() = nc | nc.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or - nc.(LocalClass).getLocalClassDeclStmt().getEnclosingCallable() = result + nc.(LocalClassOrInterface).getLocalClassDeclStmt().getEnclosingCallable() = result ) } } diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index ddae251a443..8b3cf653bde 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -786,14 +786,20 @@ class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt { override string getAPrimaryQlClass() { result = "LocalVariableDeclStmt" } } -/** A statement that declares a local class. */ +/** A statement that declares a local class or interface. */ class LocalClassDeclStmt extends Stmt, @localclassdeclstmt { /** Gets the local class declared by this statement. */ - LocalClass getLocalClass() { isLocalClass(result, this) } + LocalClassOrInterface getLocalClass() { isLocalClass(result, this) } - override string pp() { result = "class " + this.getLocalClass().toString() } + private string getDeclKeyword() { + result = "class" and this.getLocalClass() instanceof Class + or + result = "interface" and this.getLocalClass() instanceof Interface + } - override string toString() { result = "class ..." } + override string pp() { result = this.getDeclKeyword() + " " + this.getLocalClass().toString() } + + override string toString() { result = this.getDeclKeyword() + " ..." } override string getHalsteadID() { result = "LocalClassDeclStmt" } diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 5eaa52ee548..32d9abea491 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -6,8 +6,8 @@ * (`Interface`). * * Reference types can be at the top level (`TopLevelType`) or nested (`NestedType`). - * Classes can also be local (`LocalClass`) or anonymous (`AnonymousClass`). - * Enumerated types (`EnumType`) are a special kind of class. + * Classes and interfaces can also be local (`LocalClassOrInterface`, `LocalClass`) or anonymous (`AnonymousClass`). + * Enumerated types (`EnumType`) and records (`Record`) are a special kinds of class. */ import Member @@ -269,7 +269,7 @@ predicate declaresMember(Type t, @member m) { // Since the type `@member` in the dbscheme includes all `@reftype`s, // anonymous and local classes need to be excluded here. not m instanceof AnonymousClass and - not m instanceof LocalClass + not m instanceof LocalClassOrInterface } /** @@ -608,20 +608,10 @@ class SrcRefType extends RefType { } /** A class declaration. */ -class Class extends RefType, @class { +class Class extends ClassOrInterface, @class { /** Holds if this class is an anonymous class. */ predicate isAnonymous() { isAnonymClass(this, _) } - /** Holds if this class is a local class. */ - predicate isLocal() { isLocalClass(this, _) } - - /** Holds if this class is package protected, that is, neither public nor private nor protected. */ - predicate isPackageProtected() { - not isPrivate() and - not isProtected() and - not isPublic() - } - override RefType getSourceDeclaration() { classes(this, _, _, result) } /** @@ -630,11 +620,13 @@ class Class extends RefType, @class { * Note that a class may inherit annotations from super-classes. */ override Annotation getAnAnnotation() { - result = RefType.super.getAnAnnotation() + result = ClassOrInterface.super.getAnAnnotation() or exists(AnnotationType tp | tp = result.getType() | tp.isInherited() and - not exists(Annotation ann | ann = RefType.super.getAnAnnotation() | ann.getType() = tp) and + not exists(Annotation ann | ann = ClassOrInterface.super.getAnAnnotation() | + ann.getType() = tp + ) and result = this.getASupertype().(Class).getAnAnnotation() ) } @@ -643,8 +635,6 @@ class Class extends RefType, @class { } /** - * PREVIEW FEATURE in Java 14. Subject to removal in a future release. - * * A record declaration. */ class Record extends Class { @@ -727,13 +717,20 @@ class AnonymousClass extends NestedClass { override string getAPrimaryQlClass() { result = "AnonymousClass" } } -/** A local class. */ -class LocalClass extends NestedClass { - LocalClass() { this.isLocal() } +/** A local class or interface. */ +class LocalClassOrInterface extends NestedType, ClassOrInterface { + LocalClassOrInterface() { this.isLocal() } /** Gets the statement that declares this local class. */ LocalClassDeclStmt getLocalClassDeclStmt() { isLocalClass(this, result) } + override string getAPrimaryQlClass() { result = "LocalClassOrInterface" } +} + +/** A local class. */ +class LocalClass extends LocalClassOrInterface, NestedClass { + LocalClass() { this.isLocal() } + override string getAPrimaryQlClass() { result = "LocalClass" } } @@ -847,7 +844,7 @@ class InnerClass extends NestedClass { } /** An interface. */ -class Interface extends RefType, @interface { +class Interface extends ClassOrInterface, @interface { override RefType getSourceDeclaration() { interfaces(this, _, _, result) } override predicate isAbstract() { @@ -855,21 +852,24 @@ class Interface extends RefType, @interface { any() } - /** Holds if this interface is package protected, that is, neither public nor private nor protected. */ - predicate isPackageProtected() { - not isPrivate() and - not isProtected() and - not isPublic() - } - override string getAPrimaryQlClass() { result = "Interface" } } /** A class or interface. */ class ClassOrInterface extends RefType { ClassOrInterface() { - this instanceof Class or - this instanceof Interface + this instanceof @class or + this instanceof @interface + } + + /** Holds if this class or interface is local. */ + predicate isLocal() { isLocalClass(this, _) } + + /** Holds if this class or interface is package protected, that is, neither public nor private nor protected. */ + predicate isPackageProtected() { + not isPrivate() and + not isProtected() and + not isPublic() } } diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll index 54434d895f2..9f180dcd587 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJB.qll @@ -234,10 +234,10 @@ abstract class BusinessInterface extends Interface { abstract SessionEJB getAnEJB(); /** Holds if this business interface is declared local. */ - abstract predicate isLocal(); + abstract predicate isDeclaredLocal(); /** Holds if this business interface is declared remote. */ - abstract predicate isRemote(); + abstract predicate isDeclaredRemote(); } /** @@ -259,14 +259,14 @@ class XmlSpecifiedBusinessInterface extends BusinessInterface { ) } - override predicate isLocal() { + override predicate isDeclaredLocal() { exists(EjbJarXMLFile f | this.getQualifiedName() = f.getASessionElement().getABusinessLocalElement().getACharactersSet().getCharacters() ) } - override predicate isRemote() { + override predicate isDeclaredRemote() { exists(EjbJarXMLFile f | this.getQualifiedName() = f.getASessionElement().getABusinessRemoteElement().getACharactersSet().getCharacters() @@ -295,9 +295,9 @@ class AnnotatedBusinessInterface extends BusinessInterface { result.getAnAnnotation().(BusinessInterfaceAnnotation).getANamedType() = this } - override predicate isLocal() { this instanceof LocalAnnotatedBusinessInterface } + override predicate isDeclaredLocal() { this instanceof LocalAnnotatedBusinessInterface } - override predicate isRemote() { this instanceof RemoteAnnotatedBusinessInterface } + override predicate isDeclaredRemote() { this instanceof RemoteAnnotatedBusinessInterface } } /** @@ -540,7 +540,7 @@ class XmlSpecifiedLocalHomeInterface extends LegacyEjbLocalHomeInterface { class RemoteInterface extends Interface { RemoteInterface() { this instanceof RemoteAnnotatedBusinessInterface or - this.(XmlSpecifiedBusinessInterface).isRemote() or + this.(XmlSpecifiedBusinessInterface).isDeclaredRemote() or exists(SessionEJB ejb | this = ejb.getARemoteInterface()) } diff --git a/java/ql/src/DeadCode/FLinesOfDeadCode.ql b/java/ql/src/DeadCode/FLinesOfDeadCode.ql index c5f209d557e..eccab4f3c39 100644 --- a/java/ql/src/DeadCode/FLinesOfDeadCode.ql +++ b/java/ql/src/DeadCode/FLinesOfDeadCode.ql @@ -37,7 +37,7 @@ where // Remove local classes defined in the dead method - they are reported separately as a dead // class. We keep anonymous class counts, because anonymous classes are not reported // separately. - sum(LocalClass localClass | + sum(LocalClassOrInterface localClass | localClass.getLocalClassDeclStmt().getEnclosingCallable() = deadMethod | localClass.getNumberOfLinesOfCode() diff --git a/java/ql/src/utils/Stubs.qll b/java/ql/src/utils/Stubs.qll index 96b7d2332fa..4b57fd17e3d 100644 --- a/java/ql/src/utils/Stubs.qll +++ b/java/ql/src/utils/Stubs.qll @@ -8,15 +8,10 @@ import java /** A type that should be in the generated code. */ -abstract private class GeneratedType extends RefType { +abstract private class GeneratedType extends ClassOrInterface { GeneratedType() { - ( - this instanceof Interface - or - this instanceof Class - ) and not this instanceof AnonymousClass and - not this instanceof LocalClass and + not this.isLocal() and not this.getPackage() instanceof ExcludedPackage } From ac43ad6da26ce68418a6b3df65734784f02bb998 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Mon, 23 Aug 2021 19:15:20 +0100 Subject: [PATCH 414/429] Add change note --- java/change-notes/2021-08-23-local-interfaces-enums.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 java/change-notes/2021-08-23-local-interfaces-enums.md diff --git a/java/change-notes/2021-08-23-local-interfaces-enums.md b/java/change-notes/2021-08-23-local-interfaces-enums.md new file mode 100644 index 00000000000..fd324cebba9 --- /dev/null +++ b/java/change-notes/2021-08-23-local-interfaces-enums.md @@ -0,0 +1,2 @@ +lgtm,codescanning +* `Class.isLocal` has been replaced with `ClassOrInterface.isLocal`. This is because as of Java 16, interfaces can be declared method-local. Accordingly, `LocalClassDeclStmt.getLocalClass` now returns a `ClassOrInterface`. `BusinessInterface`, declared in `EJB.qll`, has had its `isRemote` and `isLocal` methods renamed `isDeclaredLocal` and `isRemoteLocal` to avoid a name clash. From fca561351da6a2d77bfeda17bc7b80053bf949b5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 24 Aug 2021 10:41:53 +0100 Subject: [PATCH 415/429] Fix typo Co-authored-by: Marcono1234 --- java/ql/lib/semmle/code/java/Type.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 32d9abea491..76e82320e25 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -7,7 +7,7 @@ * * Reference types can be at the top level (`TopLevelType`) or nested (`NestedType`). * Classes and interfaces can also be local (`LocalClassOrInterface`, `LocalClass`) or anonymous (`AnonymousClass`). - * Enumerated types (`EnumType`) and records (`Record`) are a special kinds of class. + * Enumerated types (`EnumType`) and records (`Record`) are special kinds of classes. */ import Member From 474d983f8dddd281f7fb2994032c4dcab5bcc46e Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 1 Sep 2021 15:06:49 +0100 Subject: [PATCH 416/429] Fix typo Co-authored-by: Anders Schack-Mulligen --- java/change-notes/2021-08-23-local-interfaces-enums.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/change-notes/2021-08-23-local-interfaces-enums.md b/java/change-notes/2021-08-23-local-interfaces-enums.md index fd324cebba9..ee34dcbb675 100644 --- a/java/change-notes/2021-08-23-local-interfaces-enums.md +++ b/java/change-notes/2021-08-23-local-interfaces-enums.md @@ -1,2 +1,2 @@ lgtm,codescanning -* `Class.isLocal` has been replaced with `ClassOrInterface.isLocal`. This is because as of Java 16, interfaces can be declared method-local. Accordingly, `LocalClassDeclStmt.getLocalClass` now returns a `ClassOrInterface`. `BusinessInterface`, declared in `EJB.qll`, has had its `isRemote` and `isLocal` methods renamed `isDeclaredLocal` and `isRemoteLocal` to avoid a name clash. +* `Class.isLocal` has been replaced with `ClassOrInterface.isLocal`. This is because as of Java 16, interfaces can be declared method-local. Accordingly, `LocalClassDeclStmt.getLocalClass` now returns a `ClassOrInterface`. `BusinessInterface`, declared in `EJB.qll`, has had its `isRemote` and `isLocal` methods renamed `isDeclaredLocal` and `isDeclaredRemote` to avoid a name clash. From 0a5410c2d32236ec4a91653e60c59ddc598dcde0 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 12:19:12 +0100 Subject: [PATCH 417/429] Remove unnecessary charpred --- java/ql/lib/semmle/code/java/Type.qll | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 76e82320e25..04c05eeee6b 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -856,12 +856,7 @@ class Interface extends ClassOrInterface, @interface { } /** A class or interface. */ -class ClassOrInterface extends RefType { - ClassOrInterface() { - this instanceof @class or - this instanceof @interface - } - +class ClassOrInterface extends RefType, @classorinterface { /** Holds if this class or interface is local. */ predicate isLocal() { isLocalClass(this, _) } From 608d24f75e9eb9b97996ed65b7789e5426e4f471 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 12:30:54 +0100 Subject: [PATCH 418/429] Rename QL elements that refer to local classes --- .../2021-08-23-local-interfaces-enums.md | 2 +- .../lib/semmle/code/java/ControlFlowGraph.qll | 2 +- java/ql/lib/semmle/code/java/Member.qll | 2 +- .../lib/semmle/code/java/PrettyPrintAst.qll | 4 +-- java/ql/lib/semmle/code/java/PrintAst.qll | 14 +++++++--- java/ql/lib/semmle/code/java/Statement.qll | 28 +++++++++++++------ java/ql/lib/semmle/code/java/Type.qll | 10 +++++-- java/ql/lib/semmle/code/java/dataflow/SSA.qll | 2 +- .../code/java/dataflow/internal/BaseSSA.qll | 2 +- java/ql/src/DeadCode/FLinesOfDeadCode.ql | 2 +- .../src/Likely Bugs/Statements/UseBraces.ql | 4 +-- 11 files changed, 48 insertions(+), 24 deletions(-) diff --git a/java/change-notes/2021-08-23-local-interfaces-enums.md b/java/change-notes/2021-08-23-local-interfaces-enums.md index ee34dcbb675..055bd678056 100644 --- a/java/change-notes/2021-08-23-local-interfaces-enums.md +++ b/java/change-notes/2021-08-23-local-interfaces-enums.md @@ -1,2 +1,2 @@ lgtm,codescanning -* `Class.isLocal` has been replaced with `ClassOrInterface.isLocal`. This is because as of Java 16, interfaces can be declared method-local. Accordingly, `LocalClassDeclStmt.getLocalClass` now returns a `ClassOrInterface`. `BusinessInterface`, declared in `EJB.qll`, has had its `isRemote` and `isLocal` methods renamed `isDeclaredLocal` and `isDeclaredRemote` to avoid a name clash. +* `Class.isLocal` has been replaced with `ClassOrInterface.isLocal`. This is because as of Java 16, interfaces can be declared method-local. Accordingly, `LocalClassDeclStmt.getLocalClass` is renamed `LocalTypeDeclStmt.getLocalType` and now returns a `ClassOrInterface`. `BusinessInterface`, declared in `EJB.qll`, has had its `isRemote` and `isLocal` methods renamed `isDeclaredLocal` and `isDeclaredRemote` to avoid a name clash. diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index dc38ffb1a8f..ff60abb4e73 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -456,7 +456,7 @@ private module ControlFlowGraphImpl { or this instanceof EmptyStmt or - this instanceof LocalClassDeclStmt + this instanceof LocalTypeDeclStmt or this instanceof AssertStmt } diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 50d8e2f0310..6b355352357 100755 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -45,7 +45,7 @@ class Member extends Element, Annotatable, Modifiable, @member { Callable getEnclosingCallable() { exists(NestedClass nc | this.getDeclaringType() = nc | nc.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or - nc.(LocalClassOrInterface).getLocalClassDeclStmt().getEnclosingCallable() = result + nc.(LocalClassOrInterface).getLocalTypeDeclStmt().getEnclosingCallable() = result ) } } diff --git a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll index 770cac13ec1..45e683a2466 100644 --- a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll @@ -877,8 +877,8 @@ private class PpLocalVariableDeclStmt extends PpAst, LocalVariableDeclStmt { } } -private class PpLocalClassDeclStmt extends PpAst, LocalClassDeclStmt { - override PpAst getChild(int i) { i = 0 and result = this.getLocalClass() } +private class PpLocalTypeDeclStmt extends PpAst, LocalTypeDeclStmt { + override PpAst getChild(int i) { i = 0 and result = this.getLocalType() } } /* diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 66f1ecc9449..d22065177bc 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -303,19 +303,25 @@ final class ClassInstanceExprNode extends ExprStmtNode { } /** - * A node representing a `LocalClassDeclStmt`. + * A node representing a `LocalTypeDeclStmt`. */ -final class LocalClassDeclStmtNode extends ExprStmtNode { - LocalClassDeclStmtNode() { element instanceof LocalClassDeclStmt } +final class LocalTypeDeclStmtNode extends ExprStmtNode { + LocalTypeDeclStmtNode() { element instanceof LocalTypeDeclStmt } override ElementNode getChild(int childIndex) { result = super.getChild(childIndex) or childIndex = 0 and - result.getElement() = element.(LocalClassDeclStmt).getLocalClass() + result.getElement() = element.(LocalTypeDeclStmt).getLocalType() } } +/** + * DEPRECATED: Renamed `LocalTypeDeclStmtNode` to reflect the fact that + * as of Java 16 interfaces can also be declared locally, not just classes. + */ +deprecated class LocalClassDeclStmtNode = LocalTypeDeclStmtNode; + /** * A node representing a `ForStmt`. */ diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index 8b3cf653bde..0280864ac13 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -787,25 +787,37 @@ class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt { } /** A statement that declares a local class or interface. */ -class LocalClassDeclStmt extends Stmt, @localclassdeclstmt { - /** Gets the local class declared by this statement. */ - LocalClassOrInterface getLocalClass() { isLocalClass(result, this) } +class LocalTypeDeclStmt extends Stmt, @localclassdeclstmt { + /** Gets the local type declared by this statement. */ + LocalClassOrInterface getLocalType() { isLocalClass(result, this) } + + /** + * DEPRECATED: Renamed `getLocalType` to reflect the fact that + * as of Java 16 interfaces can also be declared locally, not just classes. + */ + deprecated LocalClassOrInterface getLocalClass() { result = this.getLocalType() } private string getDeclKeyword() { - result = "class" and this.getLocalClass() instanceof Class + result = "class" and this.getLocalType() instanceof Class or - result = "interface" and this.getLocalClass() instanceof Interface + result = "interface" and this.getLocalType() instanceof Interface } - override string pp() { result = this.getDeclKeyword() + " " + this.getLocalClass().toString() } + override string pp() { result = this.getDeclKeyword() + " " + this.getLocalType().toString() } override string toString() { result = this.getDeclKeyword() + " ..." } - override string getHalsteadID() { result = "LocalClassDeclStmt" } + override string getHalsteadID() { result = "LocalTypeDeclStmt" } - override string getAPrimaryQlClass() { result = "LocalClassDeclStmt" } + override string getAPrimaryQlClass() { result = "LocalTypeDeclStmt" } } +/** + * DEPRECATED: Renamed `LocalTypeDeclStmt` to reflect the fact that + * as of Java 16 interfaces can also be declared locally, not just classes. + */ +deprecated class LocalClassDeclStmt = LocalTypeDeclStmt; + /** An explicit `this(...)` constructor invocation. */ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructorinvocationstmt { /** Gets an argument of this constructor invocation. */ diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 04c05eeee6b..c6934b96c73 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -722,7 +722,13 @@ class LocalClassOrInterface extends NestedType, ClassOrInterface { LocalClassOrInterface() { this.isLocal() } /** Gets the statement that declares this local class. */ - LocalClassDeclStmt getLocalClassDeclStmt() { isLocalClass(this, result) } + LocalTypeDeclStmt getLocalTypeDeclStmt() { isLocalClass(this, result) } + + /** + * DEPRECATED: renamed `getLocalTypeDeclStmt` to reflect the fact that + * as of Java 16 interfaces can also be declared locally. + */ + deprecated LocalTypeDeclStmt getLocalClassDeclStmt() { result = this.getLocalTypeDeclStmt() } override string getAPrimaryQlClass() { result = "LocalClassOrInterface" } } @@ -839,7 +845,7 @@ class InnerClass extends NestedClass { predicate hasEnclosingInstance() { // JLS 15.9.2. Determining Enclosing Instances not this.(AnonymousClass).getClassInstanceExpr().isInStaticContext() and - not this.(LocalClass).getLocalClassDeclStmt().getEnclosingCallable().isStatic() + not this.(LocalClass).getLocalTypeDeclStmt().getEnclosingCallable().isStatic() } } diff --git a/java/ql/lib/semmle/code/java/dataflow/SSA.qll b/java/ql/lib/semmle/code/java/dataflow/SSA.qll index 81f4a23effb..9a2a1df0915 100644 --- a/java/ql/lib/semmle/code/java/dataflow/SSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/SSA.qll @@ -238,7 +238,7 @@ private module SsaImpl { /** Gets the definition point of a nested class in the parent scope. */ private ControlFlowNode parentDef(NestedClass nc) { nc.(AnonymousClass).getClassInstanceExpr() = result or - nc.(LocalClass).getLocalClassDeclStmt() = result + nc.(LocalClass).getLocalTypeDeclStmt() = result } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index d6532823b44..8193a33bcb3 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -79,7 +79,7 @@ private module SsaImpl { /** Gets the definition point of a nested class in the parent scope. */ private ControlFlowNode parentDef(NestedClass nc) { nc.(AnonymousClass).getClassInstanceExpr() = result or - nc.(LocalClass).getLocalClassDeclStmt() = result + nc.(LocalClass).getLocalTypeDeclStmt() = result } /** diff --git a/java/ql/src/DeadCode/FLinesOfDeadCode.ql b/java/ql/src/DeadCode/FLinesOfDeadCode.ql index eccab4f3c39..0137778e744 100644 --- a/java/ql/src/DeadCode/FLinesOfDeadCode.ql +++ b/java/ql/src/DeadCode/FLinesOfDeadCode.ql @@ -38,7 +38,7 @@ where // class. We keep anonymous class counts, because anonymous classes are not reported // separately. sum(LocalClassOrInterface localClass | - localClass.getLocalClassDeclStmt().getEnclosingCallable() = deadMethod + localClass.getLocalTypeDeclStmt().getEnclosingCallable() = deadMethod | localClass.getNumberOfLinesOfCode() ) diff --git a/java/ql/src/Likely Bugs/Statements/UseBraces.ql b/java/ql/src/Likely Bugs/Statements/UseBraces.ql index 1d844cfe913..e9c8a082f3f 100644 --- a/java/ql/src/Likely Bugs/Statements/UseBraces.ql +++ b/java/ql/src/Likely Bugs/Statements/UseBraces.ql @@ -122,8 +122,8 @@ where not abortsControlFlow(s) and // Exclude the double semicolon case `if (cond) s;;`. not t instanceof EmptyStmt and - // `LocalClassDeclStmt`s yield false positives since their `Location` doesn't include the `class` keyword. - not t instanceof LocalClassDeclStmt + // `LocalTypeDeclStmt`s yield false positives since their `Location` doesn't include the `class` keyword. + not t instanceof LocalTypeDeclStmt select s, "Indentation suggests that $@ belongs to $@, but this is not the case; consider adding braces or adjusting indentation.", t, "the next statement", c, "the control structure" From e8bdc8ba17f6a5e202779f75079bbc8b56cbc1e5 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 14:20:14 +0100 Subject: [PATCH 419/429] Make Member.getEnclosingCallable compatible with local interfaces --- java/ql/lib/semmle/code/java/Member.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 6b355352357..da136c577f8 100755 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -40,12 +40,12 @@ class Member extends Element, Annotatable, Modifiable, @member { /** * Gets the immediately enclosing callable, if this member is declared in - * an anonymous or local class. + * an anonymous or local class or interface. */ Callable getEnclosingCallable() { - exists(NestedClass nc | this.getDeclaringType() = nc | - nc.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or - nc.(LocalClassOrInterface).getLocalTypeDeclStmt().getEnclosingCallable() = result + exists(NestedType nt | this.getDeclaringType() = nt | + nt.(AnonymousClass).getClassInstanceExpr().getEnclosingCallable() = result or + nt.(LocalClassOrInterface).getLocalTypeDeclStmt().getEnclosingCallable() = result ) } } From 29b9231f4929cf39841eaef50d99b48fe4857150 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 14:47:23 +0100 Subject: [PATCH 420/429] Rename db types relating to local classes These now all refer to types or classes-or-interfaces. --- java/ql/lib/config/semmlecode.dbscheme | 10 +++++----- java/ql/lib/config/semmlecode.dbscheme.stats | 2 +- java/ql/lib/semmle/code/java/Statement.qll | 4 ++-- java/ql/lib/semmle/code/java/Type.qll | 4 ++-- .../semmlecode.dbscheme | 10 +++++----- .../upgrade.properties | 2 ++ 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index 0572efbc095..8ab354e68e8 100755 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -440,10 +440,10 @@ isAnonymClass( int parent: @classinstancexpr ref ); -#keyset[classid] #keyset[parent] -isLocalClass( - int classid: @classorinterface ref, - int parent: @localclassdeclstmt ref +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref ); isDefConstr( @@ -526,7 +526,7 @@ case @stmt.kind of | 15 = @labeledstmt | 16 = @assertstmt | 17 = @localvariabledeclstmt -| 18 = @localclassdeclstmt +| 18 = @localtypedeclstmt | 19 = @constructorinvocationstmt | 20 = @superconstructorinvocationstmt | 21 = @case diff --git a/java/ql/lib/config/semmlecode.dbscheme.stats b/java/ql/lib/config/semmlecode.dbscheme.stats index cccd0da8b75..18382a8cb20 100644 --- a/java/ql/lib/config/semmlecode.dbscheme.stats +++ b/java/ql/lib/config/semmlecode.dbscheme.stats @@ -16910,7 +16910,7 @@
    -isLocalClass +isLocalClassOrInterface 349 diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index 0280864ac13..a5f9eb81080 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -787,9 +787,9 @@ class LocalVariableDeclStmt extends Stmt, @localvariabledeclstmt { } /** A statement that declares a local class or interface. */ -class LocalTypeDeclStmt extends Stmt, @localclassdeclstmt { +class LocalTypeDeclStmt extends Stmt, @localtypedeclstmt { /** Gets the local type declared by this statement. */ - LocalClassOrInterface getLocalType() { isLocalClass(result, this) } + LocalClassOrInterface getLocalType() { isLocalClassOrInterface(result, this) } /** * DEPRECATED: Renamed `getLocalType` to reflect the fact that diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index c6934b96c73..3b05665d055 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -722,7 +722,7 @@ class LocalClassOrInterface extends NestedType, ClassOrInterface { LocalClassOrInterface() { this.isLocal() } /** Gets the statement that declares this local class. */ - LocalTypeDeclStmt getLocalTypeDeclStmt() { isLocalClass(this, result) } + LocalTypeDeclStmt getLocalTypeDeclStmt() { isLocalClassOrInterface(this, result) } /** * DEPRECATED: renamed `getLocalTypeDeclStmt` to reflect the fact that @@ -864,7 +864,7 @@ class Interface extends ClassOrInterface, @interface { /** A class or interface. */ class ClassOrInterface extends RefType, @classorinterface { /** Holds if this class or interface is local. */ - predicate isLocal() { isLocalClass(this, _) } + predicate isLocal() { isLocalClassOrInterface(this, _) } /** Holds if this class or interface is package protected, that is, neither public nor private nor protected. */ predicate isPackageProtected() { diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme index 0572efbc095..8ab354e68e8 100755 --- a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/semmlecode.dbscheme @@ -440,10 +440,10 @@ isAnonymClass( int parent: @classinstancexpr ref ); -#keyset[classid] #keyset[parent] -isLocalClass( - int classid: @classorinterface ref, - int parent: @localclassdeclstmt ref +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref ); isDefConstr( @@ -526,7 +526,7 @@ case @stmt.kind of | 15 = @labeledstmt | 16 = @assertstmt | 17 = @localvariabledeclstmt -| 18 = @localclassdeclstmt +| 18 = @localtypedeclstmt | 19 = @constructorinvocationstmt | 20 = @superconstructorinvocationstmt | 21 = @case diff --git a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties index 1cff2f6073f..459f9588323 100644 --- a/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties +++ b/java/upgrades/b4e689c90426b017ad550e30a439cab2763ff424/upgrade.properties @@ -1,2 +1,4 @@ description: Java 16: allow local interfaces compatibility: backwards +isLocalClassOrInterface.rel: reorder isLocalClass.rel(int id, int parent) id parent +isLocalClass.rel: delete From b9afccc01585f9bda200b07474026a05c2a142cc Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 17:14:38 +0100 Subject: [PATCH 421/429] Remove impossible lines from Stubs.qll --- java/ql/src/utils/Stubs.qll | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/ql/src/utils/Stubs.qll b/java/ql/src/utils/Stubs.qll index 4b57fd17e3d..3f3781d527b 100644 --- a/java/ql/src/utils/Stubs.qll +++ b/java/ql/src/utils/Stubs.qll @@ -129,8 +129,6 @@ private class IndirectType extends GeneratedType { or this = any(GeneratedType t).getSourceDeclaration() or - exists(GeneratedType t | this = t.(BoundedType).getATypeBound().getType()) - or exists(GeneratedDeclaration decl | decl.(Member).getDeclaringType().getSourceDeclaration() = this ) @@ -138,8 +136,6 @@ private class IndirectType extends GeneratedType { this.(NestedType).getEnclosingType() instanceof GeneratedType or exists(NestedType nt | nt instanceof GeneratedType and this = nt.getEnclosingType()) - or - this = any(GeneratedType a).(Array).getComponentType() } } From c259d0204a1a327fb2436116680842c64ddce133 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 17:53:52 +0100 Subject: [PATCH 422/429] Move unreachable cases of IndirectType into getAContainedType --- java/ql/src/utils/Stubs.qll | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/java/ql/src/utils/Stubs.qll b/java/ql/src/utils/Stubs.qll index 96b7d2332fa..3a6cdf92817 100644 --- a/java/ql/src/utils/Stubs.qll +++ b/java/ql/src/utils/Stubs.qll @@ -8,13 +8,8 @@ import java /** A type that should be in the generated code. */ -abstract private class GeneratedType extends RefType { +abstract private class GeneratedType extends ClassOrInterface { GeneratedType() { - ( - this instanceof Interface - or - this instanceof Class - ) and not this instanceof AnonymousClass and not this instanceof LocalClass and not this.getPackage() instanceof ExcludedPackage @@ -134,8 +129,6 @@ private class IndirectType extends GeneratedType { or this = any(GeneratedType t).getSourceDeclaration() or - exists(GeneratedType t | this = t.(BoundedType).getATypeBound().getType()) - or exists(GeneratedDeclaration decl | decl.(Member).getDeclaringType().getSourceDeclaration() = this ) @@ -143,8 +136,6 @@ private class IndirectType extends GeneratedType { this.(NestedType).getEnclosingType() instanceof GeneratedType or exists(NestedType nt | nt instanceof GeneratedType and this = nt.getEnclosingType()) - or - this = any(GeneratedType a).(Array).getComponentType() } } @@ -156,6 +147,10 @@ private Type getAContainedType(Type t) { result = t or result = getAContainedType(t.(ParameterizedType).getATypeArgument()) + or + result = getAContainedType(t.(Array).getElementType()) + or + result = getAContainedType(t.(BoundedType).getATypeBound().getType()) } /** From d57bd34575c0e602abc02c492fd0e4d263bbbbf7 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 2 Sep 2021 20:14:51 +0100 Subject: [PATCH 423/429] Update dbscheme stats --- java/ql/lib/config/semmlecode.dbscheme.stats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/config/semmlecode.dbscheme.stats b/java/ql/lib/config/semmlecode.dbscheme.stats index 18382a8cb20..4d591b9ae2e 100644 --- a/java/ql/lib/config/semmlecode.dbscheme.stats +++ b/java/ql/lib/config/semmlecode.dbscheme.stats @@ -169,7 +169,7 @@ 223232 -@localclassdeclstmt +@localtypedeclstmt 349 @@ -16914,7 +16914,7 @@ 349 -classid +typeid 349 From 3560853f36e147409ccce79bc7d880192954831d Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 3 Sep 2021 09:53:34 +0200 Subject: [PATCH 424/429] C#: Fix ordering of stubbed type members, implemented interfaces, and location comments --- csharp/ql/src/Stubs/Stubs.qll | 7 ++++--- csharp/ql/test/query-tests/Stubs/All/AllStubs.expected | 2 +- .../Stubs/Minimal/MinimalStubsFromSource.expected | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 4a178980a52..8971c89ba9b 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -122,7 +122,8 @@ abstract private class GeneratedType extends Type, GeneratedElement { private string stubComment() { result = "// Generated from `" + this.getQualifiedName() + "` in `" + - concat(this.getALocation().toString(), "; ") + "`\n" + concat(Location l | l = this.getALocation() | l.toString(), "; " order by l.toString()) + + "`\n" } /** Gets the entire C# stub code for this type. */ @@ -169,7 +170,7 @@ abstract private class GeneratedType extends Type, GeneratedElement { t = this.getAnInterestingBaseType() and (if t instanceof Class then i = 0 else i = 1) | - stubClassName(t), ", " order by i + stubClassName(t), ", " order by i, t.getQualifiedName() ) else result = "" } @@ -180,7 +181,7 @@ abstract private class GeneratedType extends Type, GeneratedElement { concat(GeneratedMember m | m = this.getAGeneratedMember(assembly) | - stubMember(m, assembly) order by m.getName() + stubMember(m, assembly) order by m.getQualifiedNameWithTypes() ) } diff --git a/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected b/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected index 05b68090748..94d3a4fe826 100644 --- a/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected +++ b/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n\nnamespace A1\n{\n// Generated from `A1.C1` in `Test.cs:146:18:146:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C1\n{\n}\n\n}\nnamespace A2\n{\nnamespace B2\n{\n// Generated from `A2.B2.C2` in `Test.cs:153:22:153:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C2\n{\n}\n\n}\n}\nnamespace A3\n{\n// Generated from `A3.C3` in `Test.cs:159:18:159:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C3\n{\n}\n\n}\nnamespace A4\n{\n// Generated from `A4.C4` in `Test.cs:169:18:169:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C4\n{\n}\n\nnamespace B4\n{\n// Generated from `A4.B4.D4` in `Test.cs:166:22:166:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class D4\n{\n}\n\n}\n}\nnamespace Test\n{\n// Generated from `Test.Class1` in `Test.cs:5:18:5:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class1\n{\n// Generated from `Test.Class1+Class11` in `Test.cs:34:22:34:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class11 : Test.Class1.Interface2, Test.Class1.Interface1\n{\n int Test.Class1.Interface2.this[int i] { get => throw null; }\n public void Method1() => throw null;\n void Test.Class1.Interface2.Method2() => throw null;\n}\n\n\n// Generated from `Test.Class1+Class12` in `Test.cs:51:22:51:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class12 : Test.Class1.Class11\n{\n}\n\n\n// Generated from `Test.Class1+Class13` in `Test.cs:63:31:63:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class13\n{\n protected internal virtual void M() => throw null;\n public virtual void M1() where T: Test.Class1.Class13 => throw null;\n public abstract void M2();\n}\n\n\n// Generated from `Test.Class1+Class14` in `Test.cs:70:31:70:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class14 : Test.Class1.Class13\n{\n protected internal override void M() => throw null;\n public override void M1() => throw null;\n public abstract override void M2();\n}\n\n\n// Generated from `Test.Class1+Delegate1<>` in `Test.cs:47:30:47:41; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic delegate void Delegate1(T i, int j);\n\n\n public event Test.Class1.Delegate1 Event1;\n// Generated from `Test.Class1+GenericType<>` in `Test.cs:56:22:56:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class GenericType\n{\n// Generated from `Test.Class1+GenericType<>+X` in `Test.cs:58:26:58:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class X\n{\n}\n\n\n}\n\n\n// Generated from `Test.Class1+Interface1` in `Test.cs:18:26:18:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface Interface1\n{\n void Method1();\n}\n\n\n// Generated from `Test.Class1+Interface2` in `Test.cs:23:38:23:47; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\nprotected internal interface Interface2\n{\n int this[int i] { get; }\n void Method2();\n}\n\n\n public Test.Class1.GenericType.X Prop { get => throw null; }\n// Generated from `Test.Class1+Struct1` in `Test.cs:7:23:7:29; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic struct Struct1\n{\n public void Method(Test.Class1.Struct1 s = default(Test.Class1.Struct1)) => throw null;\n public int i;\n public static int j = default;\n public System.ValueTuple t1;\n public (int,int) t2;\n}\n\n\n}\n\n// Generated from `Test.Class3` in `Test.cs:84:18:84:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class3\n{\n public object Item { get => throw null; set => throw null; }\n [System.Runtime.CompilerServices.IndexerName("MyItem")]\n public object this[string index] { get => throw null; set => throw null; }\n}\n\n// Generated from `Test.Class4` in `Test.cs:91:18:91:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class4\n{\n unsafe public void M(int* p) => throw null;\n}\n\n// Generated from `Test.Class5` in `Test.cs:102:18:102:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class5 : Test.IInterface1\n{\n public void M2() => throw null;\n}\n\n// Generated from `Test.Class6<>` in `Test.cs:107:18:107:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class6 where T: class, Test.IInterface1\n{\n public virtual void M1() where T: class, Test.IInterface1, new() => throw null;\n}\n\n// Generated from `Test.Class7` in `Test.cs:114:18:114:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class7 : Test.Class6\n{\n public override void M1() where T: class => throw null;\n}\n\n// Generated from `Test.Class8` in `Test.cs:121:18:121:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class8\n{\n public static int @this = default;\n}\n\n// Generated from `Test.Class9` in `Test.cs:126:18:126:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class9\n{\n// Generated from `Test.Class9+Nested` in `Test.cs:130:22:130:27; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Nested : Test.Class9\n{\n}\n\n\n public Test.Class9.Nested NestedInstance { get => throw null; }\n}\n\n// Generated from `Test.IInterface1` in `Test.cs:96:22:96:32; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IInterface1\n{\n void M1() => throw null;\n void M2();\n}\n\n}\n\n\n | +| // This file contains auto-generated code.\n\nnamespace A1\n{\n// Generated from `A1.C1` in `Test.cs:146:18:146:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C1\n{\n}\n\n}\nnamespace A2\n{\nnamespace B2\n{\n// Generated from `A2.B2.C2` in `Test.cs:153:22:153:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C2\n{\n}\n\n}\n}\nnamespace A3\n{\n// Generated from `A3.C3` in `Test.cs:159:18:159:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C3\n{\n}\n\n}\nnamespace A4\n{\n// Generated from `A4.C4` in `Test.cs:169:18:169:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C4\n{\n}\n\nnamespace B4\n{\n// Generated from `A4.B4.D4` in `Test.cs:166:22:166:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class D4\n{\n}\n\n}\n}\nnamespace Test\n{\n// Generated from `Test.Class1` in `Test.cs:5:18:5:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class1\n{\n// Generated from `Test.Class1+Class11` in `Test.cs:34:22:34:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class11 : Test.Class1.Interface1, Test.Class1.Interface2\n{\n int Test.Class1.Interface2.this[int i] { get => throw null; }\n public void Method1() => throw null;\n void Test.Class1.Interface2.Method2() => throw null;\n}\n\n\n// Generated from `Test.Class1+Class12` in `Test.cs:51:22:51:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class12 : Test.Class1.Class11\n{\n}\n\n\n// Generated from `Test.Class1+Class13` in `Test.cs:63:31:63:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class13\n{\n protected internal virtual void M() => throw null;\n public virtual void M1() where T: Test.Class1.Class13 => throw null;\n public abstract void M2();\n}\n\n\n// Generated from `Test.Class1+Class14` in `Test.cs:70:31:70:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class14 : Test.Class1.Class13\n{\n protected internal override void M() => throw null;\n public override void M1() => throw null;\n public abstract override void M2();\n}\n\n\n// Generated from `Test.Class1+Delegate1<>` in `Test.cs:47:30:47:41; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic delegate void Delegate1(T i, int j);\n\n\n// Generated from `Test.Class1+GenericType<>` in `Test.cs:56:22:56:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class GenericType\n{\n// Generated from `Test.Class1+GenericType<>+X` in `Test.cs:58:26:58:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class X\n{\n}\n\n\n}\n\n\n// Generated from `Test.Class1+Interface1` in `Test.cs:18:26:18:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface Interface1\n{\n void Method1();\n}\n\n\n// Generated from `Test.Class1+Interface2` in `Test.cs:23:38:23:47; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\nprotected internal interface Interface2\n{\n int this[int i] { get; }\n void Method2();\n}\n\n\n// Generated from `Test.Class1+Struct1` in `Test.cs:7:23:7:29; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic struct Struct1\n{\n public void Method(Test.Class1.Struct1 s = default(Test.Class1.Struct1)) => throw null;\n public int i;\n public static int j = default;\n public System.ValueTuple t1;\n public (int,int) t2;\n}\n\n\n public event Test.Class1.Delegate1 Event1;\n public Test.Class1.GenericType.X Prop { get => throw null; }\n}\n\n// Generated from `Test.Class3` in `Test.cs:84:18:84:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class3\n{\n public object Item { get => throw null; set => throw null; }\n [System.Runtime.CompilerServices.IndexerName("MyItem")]\n public object this[string index] { get => throw null; set => throw null; }\n}\n\n// Generated from `Test.Class4` in `Test.cs:91:18:91:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class4\n{\n unsafe public void M(int* p) => throw null;\n}\n\n// Generated from `Test.Class5` in `Test.cs:102:18:102:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class5 : Test.IInterface1\n{\n public void M2() => throw null;\n}\n\n// Generated from `Test.Class6<>` in `Test.cs:107:18:107:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class6 where T: class, Test.IInterface1\n{\n public virtual void M1() where T: class, Test.IInterface1, new() => throw null;\n}\n\n// Generated from `Test.Class7` in `Test.cs:114:18:114:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class7 : Test.Class6\n{\n public override void M1() where T: class => throw null;\n}\n\n// Generated from `Test.Class8` in `Test.cs:121:18:121:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class8\n{\n public static int @this = default;\n}\n\n// Generated from `Test.Class9` in `Test.cs:126:18:126:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class9\n{\n// Generated from `Test.Class9+Nested` in `Test.cs:130:22:130:27; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Nested : Test.Class9\n{\n}\n\n\n public Test.Class9.Nested NestedInstance { get => throw null; }\n}\n\n// Generated from `Test.IInterface1` in `Test.cs:96:22:96:32; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IInterface1\n{\n void M1() => throw null;\n void M2();\n}\n\n}\n\n\n | diff --git a/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected b/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected index 29b1d1de1f7..8d627dfd8e6 100644 --- a/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected +++ b/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n public override string ToString() => throw null;\n}\n\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.ICloneable, System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection\n{\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual object Clone() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual int Count { get => throw null; }\n public virtual object GetByIndex(int index) => throw null;\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual void Remove(object key) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.IEnumerable, System.Collections.ICollection, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IEnumerable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n public int Count { get => throw null; }\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public T Peek() => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic abstract class NameObjectCollectionBase : System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback, System.Collections.IEnumerable, System.Collections.ICollection\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n public virtual int Count { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public virtual void OnDeserialization(object sender) => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ComponentConverter : System.ComponentModel.ReferenceConverter\n{\n}\n\n// Generated from `System.ComponentModel.DefaultEventAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultEventAttribute : System.Attribute\n{\n public DefaultEventAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.DefaultPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultPropertyAttribute : System.Attribute\n{\n public DefaultPropertyAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverter\n{\n}\n\n}\nnamespace Timers\n{\n// Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n internal TimersDescriptionAttribute(string description, string defaultValue) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverterAttribute : System.Attribute\n{\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute() => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptionProviderAttribute : System.Attribute\n{\n public TypeDescriptionProviderAttribute(string typeName) => throw null;\n public TypeDescriptionProviderAttribute(System.Type type) => throw null;\n}\n\n}\nnamespace Windows\n{\nnamespace Markup\n{\n// Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ValueSerializerAttribute : System.Attribute\n{\n public ValueSerializerAttribute(string valueSerializerTypeName) => throw null;\n public ValueSerializerAttribute(System.Type valueSerializerType) => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n internal ParallelQuery(System.Linq.Parallel.QuerySettings specifiedSettings) => throw null;\n}\n\nnamespace Parallel\n{\n// Generated from `System.Linq.Parallel.QuerySettings` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninternal struct QuerySettings\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n internal Capture(string text, int index, int length) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n internal Group(string text, int[] caps, int capcount, string name) : base(default(string), default(int), default(int)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n internal Match(System.Text.RegularExpressions.Regex regex, int capcount, string text, int begpos, int len, int startpos) : base(default(string), default(int[]), default(int), default(string)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public Regex(string pattern) => throw null;\n public string Replace(string input, string replacement) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\n[System.Flags]\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n}\n}\n}\n\n\n | +| // This file contains auto-generated code.\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Uri : System.Runtime.Serialization.ISerializable\n{\n public override bool Equals(object comparand) => throw null;\n public override int GetHashCode() => throw null;\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n public override string ToString() => throw null;\n}\n\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ICloneable\n{\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual object Clone() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual int Count { get => throw null; }\n public virtual object GetByIndex(int index) => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n public virtual bool IsFixedSize { get => throw null; }\n public virtual bool IsReadOnly { get => throw null; }\n public virtual bool IsSynchronized { get => throw null; }\n public virtual object this[object key] { get => throw null; set => throw null; }\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual void Remove(object key) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n public int Count { get => throw null; }\n System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public T Peek() => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic abstract class NameObjectCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n public virtual int Count { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public virtual void OnDeserialization(object sender) => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ComponentConverter : System.ComponentModel.ReferenceConverter\n{\n}\n\n// Generated from `System.ComponentModel.DefaultEventAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultEventAttribute : System.Attribute\n{\n public DefaultEventAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.DefaultPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DefaultPropertyAttribute : System.Attribute\n{\n public DefaultPropertyAttribute(string name) => throw null;\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n}\n\n// Generated from `System.ComponentModel.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverter\n{\n}\n\n}\nnamespace Timers\n{\n// Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n internal TimersDescriptionAttribute(string description, string defaultValue) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverterAttribute : System.Attribute\n{\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n public TypeConverterAttribute() => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeDescriptionProviderAttribute : System.Attribute\n{\n public TypeDescriptionProviderAttribute(System.Type type) => throw null;\n public TypeDescriptionProviderAttribute(string typeName) => throw null;\n}\n\n}\nnamespace Windows\n{\nnamespace Markup\n{\n// Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ValueSerializerAttribute : System.Attribute\n{\n public ValueSerializerAttribute(System.Type valueSerializerType) => throw null;\n public ValueSerializerAttribute(string valueSerializerTypeName) => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class Enumerable\n{\n public static System.Collections.Generic.IEnumerable Select(this System.Collections.Generic.IEnumerable source, System.Func selector) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\n// Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n internal ParallelQuery(System.Linq.Parallel.QuerySettings specifiedSettings) => throw null;\n}\n\nnamespace Parallel\n{\n// Generated from `System.Linq.Parallel.QuerySettings` in `System.Linq.Parallel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninternal struct QuerySettings\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\n// Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n internal Capture(string text, int index, int length) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n internal Group(string text, int[] caps, int capcount, string name) : base(default(string), default(int), default(int)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n internal Match(System.Text.RegularExpressions.Regex regex, int capcount, string text, int begpos, int len, int startpos) : base(default(string), default(int[]), default(int), default(string)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern) => throw null;\n public static System.Text.RegularExpressions.Match Match(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\n[System.Flags]\npublic enum RegexOptions\n{\n IgnoreCase,\n}\n\n}\n}\n}\n\n\n | From c06e37f3d9844b078c1abbb1a31972b170eacf84 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Fri, 3 Sep 2021 10:45:16 +0200 Subject: [PATCH 425/429] Hide diff for generated files by default --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitattributes b/.gitattributes index 9a488b7bb5c..c4fdb243019 100644 --- a/.gitattributes +++ b/.gitattributes @@ -48,3 +48,5 @@ *.gif -text *.dll -text *.pdb -text + +java/ql/test/stubs/**/*.java linguist-generated=true \ No newline at end of file From c20cf23c98a2992908225b57904bc43293435b49 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 3 Sep 2021 10:40:51 +0100 Subject: [PATCH 426/429] Update stats file dependencies --- java/ql/lib/config/semmlecode.dbscheme.stats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/config/semmlecode.dbscheme.stats b/java/ql/lib/config/semmlecode.dbscheme.stats index 4d591b9ae2e..ec8f878f38f 100644 --- a/java/ql/lib/config/semmlecode.dbscheme.stats +++ b/java/ql/lib/config/semmlecode.dbscheme.stats @@ -16924,7 +16924,7 @@ -classid +typeid parent @@ -16941,7 +16941,7 @@ parent -classid +typeid 12 From f59a5b65746ec59d5064626b751b31e370a179a2 Mon Sep 17 00:00:00 2001 From: Benjamin Muskalla Date: Fri, 3 Sep 2021 14:16:04 +0200 Subject: [PATCH 427/429] Hide changes for experimenal stubs --- .gitattributes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index c4fdb243019..e705e8f40d9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -49,4 +49,5 @@ *.dll -text *.pdb -text -java/ql/test/stubs/**/*.java linguist-generated=true \ No newline at end of file +java/ql/test/stubs/**/*.java linguist-generated=true +java/ql/test/experimental/stubs/**/*.java linguist-generated=true \ No newline at end of file From c02a743835a9154649f0ab8233d125f49f5657a5 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 3 Sep 2021 16:51:32 +0200 Subject: [PATCH 428/429] Revert redundant order by --- csharp/ql/src/Stubs/Stubs.qll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 8971c89ba9b..55fedec2c74 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -122,8 +122,7 @@ abstract private class GeneratedType extends Type, GeneratedElement { private string stubComment() { result = "// Generated from `" + this.getQualifiedName() + "` in `" + - concat(Location l | l = this.getALocation() | l.toString(), "; " order by l.toString()) + - "`\n" + concat(this.getALocation().toString(), "; ") + "`\n" } /** Gets the entire C# stub code for this type. */ From 23d7633cd5ceaddd820db83b698c42f7832d2dee Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Fri, 3 Sep 2021 18:20:16 +0100 Subject: [PATCH 429/429] Add tests for static and final modifiers relating to record classes --- .../record-classes/MyFinalRecord.java | 1 + .../library-tests/record-classes/MyRecord.java | 2 ++ .../record-classes/RecordClasses.expected | 6 ++++++ .../library-tests/record-classes/RecordClasses.ql | 8 ++++++++ .../ql/test/library-tests/record-classes/Test.java | 14 ++++++++++++++ java/ql/test/library-tests/record-classes/options | 1 + 6 files changed, 32 insertions(+) create mode 100644 java/ql/test/library-tests/record-classes/MyFinalRecord.java create mode 100644 java/ql/test/library-tests/record-classes/MyRecord.java create mode 100644 java/ql/test/library-tests/record-classes/RecordClasses.expected create mode 100644 java/ql/test/library-tests/record-classes/RecordClasses.ql create mode 100644 java/ql/test/library-tests/record-classes/Test.java create mode 100644 java/ql/test/library-tests/record-classes/options diff --git a/java/ql/test/library-tests/record-classes/MyFinalRecord.java b/java/ql/test/library-tests/record-classes/MyFinalRecord.java new file mode 100644 index 00000000000..08edac786c9 --- /dev/null +++ b/java/ql/test/library-tests/record-classes/MyFinalRecord.java @@ -0,0 +1 @@ +final record MyFinalRecord() { } diff --git a/java/ql/test/library-tests/record-classes/MyRecord.java b/java/ql/test/library-tests/record-classes/MyRecord.java new file mode 100644 index 00000000000..f3ccd8f3cea --- /dev/null +++ b/java/ql/test/library-tests/record-classes/MyRecord.java @@ -0,0 +1,2 @@ +// Records are implicitly final +record MyRecord() { } diff --git a/java/ql/test/library-tests/record-classes/RecordClasses.expected b/java/ql/test/library-tests/record-classes/RecordClasses.expected new file mode 100644 index 00000000000..d1c49d62066 --- /dev/null +++ b/java/ql/test/library-tests/record-classes/RecordClasses.expected @@ -0,0 +1,6 @@ +| MyFinalRecord.java:1:14:1:26 | MyFinalRecord | final=true | static=false | Record | +| MyRecord.java:2:8:2:15 | MyRecord | final=true | static=false | Record | +| Test.java:3:12:3:13 | R1 | final=true | static=true | Record | +| Test.java:4:25:4:26 | R2 | final=true | static=true | Record | +| Test.java:8:12:8:13 | R3 | final=true | static=true | Record,SuperInterface | +| Test.java:12:16:12:26 | LocalRecord | final=true | static=true | Record | diff --git a/java/ql/test/library-tests/record-classes/RecordClasses.ql b/java/ql/test/library-tests/record-classes/RecordClasses.ql new file mode 100644 index 00000000000..ecc9f5e957c --- /dev/null +++ b/java/ql/test/library-tests/record-classes/RecordClasses.ql @@ -0,0 +1,8 @@ +import java + +from Record r, boolean isFinal, boolean isStatic, string superTypes +where + (if r.isFinal() then isFinal = true else isFinal = false) and + (if r.isStatic() then isStatic = true else isStatic = false) and + superTypes = concat(RefType superType | superType = r.getASupertype() | superType.toString(), ",") +select r, "final=" + isFinal, "static=" + isStatic, superTypes diff --git a/java/ql/test/library-tests/record-classes/Test.java b/java/ql/test/library-tests/record-classes/Test.java new file mode 100644 index 00000000000..bdf3029ce8b --- /dev/null +++ b/java/ql/test/library-tests/record-classes/Test.java @@ -0,0 +1,14 @@ +class Test { + // Nested records are implicitly static + record R1() { } + static final record R2() { } + + interface SuperInterface { } + + record R3() implements SuperInterface { } + + void test() { + // Nested records are implicitly static + record LocalRecord() { } + } +} diff --git a/java/ql/test/library-tests/record-classes/options b/java/ql/test/library-tests/record-classes/options new file mode 100644 index 00000000000..fc57fe025b9 --- /dev/null +++ b/java/ql/test/library-tests/record-classes/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -source 16 -target 16