diff --git a/config/identical-files.json b/config/identical-files.json index fb6c1d645ba..34f25f3baa7 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -7,6 +7,7 @@ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll", + "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll", diff --git a/cpp/ql/lib/semmle/code/cpp/Class.qll b/cpp/ql/lib/semmle/code/cpp/Class.qll index 4fe1b07e32a..64819a5e945 100644 --- a/cpp/ql/lib/semmle/code/cpp/Class.qll +++ b/cpp/ql/lib/semmle/code/cpp/Class.qll @@ -206,9 +206,7 @@ class Class extends UserType { * it is callable by a particular caller. For C++11, there's also a question * of whether to include members that are defaulted or deleted. */ - deprecated predicate hasCopyConstructor() { - exists(CopyConstructor cc | cc = this.getAMemberFunction()) - } + deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor } /** * Holds if this class has a copy assignment operator that is either @@ -224,7 +222,7 @@ class Class extends UserType { * or deleted. */ deprecated predicate hasCopyAssignmentOperator() { - exists(CopyAssignmentOperator coa | coa = this.getAMemberFunction()) + this.getAMemberFunction() instanceof CopyAssignmentOperator } /** @@ -887,7 +885,7 @@ class NestedClass extends Class { * pure virtual function. */ class AbstractClass extends Class { - AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) } + AbstractClass() { this.getAMemberFunction() instanceof PureVirtualFunction } override string getAPrimaryQlClass() { result = "AbstractClass" } } diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll index fe2919c3ed6..69cccf06ffb 100644 --- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll @@ -286,13 +286,13 @@ class AttributeArgument extends Element, @attribute_arg { override Location getLocation() { attribute_args(underlyingElement(this), _, _, _, result) } override string toString() { - if exists(@attribute_arg_empty self | self = underlyingElement(this)) + if underlyingElement(this) instanceof @attribute_arg_empty then result = "empty argument" else exists(string prefix, string tail | (if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and ( - if exists(@attribute_arg_type self | self = underlyingElement(this)) + if underlyingElement(this) instanceof @attribute_arg_type then tail = this.getValueType().getName() else tail = this.getValueText() ) and diff --git a/cpp/ql/lib/semmle/code/cpp/XML.qll b/cpp/ql/lib/semmle/code/cpp/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/cpp/ql/lib/semmle/code/cpp/XML.qll +++ b/cpp/ql/lib/semmle/code/cpp/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll index 5ee7245d6e7..4a6566da45d 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Printf.qll @@ -1122,7 +1122,7 @@ class FormatLiteral extends Literal { * conversion specifier of this format string; has no result if this cannot * be determined. */ - int getMaxConvertedLength(int n) { result = max(getMaxConvertedLength(n, _)) } + int getMaxConvertedLength(int n) { result = max(this.getMaxConvertedLength(n, _)) } /** * Gets the maximum length of the string that can be produced by the nth @@ -1353,7 +1353,7 @@ class FormatLiteral extends Literal { * determining whether a buffer overflow is caused by long float to string * conversions. */ - int getMaxConvertedLengthLimited(int n) { result = max(getMaxConvertedLengthLimited(n, _)) } + int getMaxConvertedLengthLimited(int n) { result = max(this.getMaxConvertedLengthLimited(n, _)) } /** * Gets the maximum length of the string that can be produced by the nth diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll index 9aee2556c1d..2b222376a0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll @@ -29,7 +29,7 @@ class GuardCondition extends Expr { exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression()) or // no binary operators in the IR - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition or // the IR short-circuits if(!x) // don't produce a guard condition for `y = !x` and other non-short-circuited cases @@ -98,7 +98,7 @@ class GuardCondition extends Expr { */ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { GuardConditionFromBinaryLogicalOperator() { - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition } override predicate controls(BasicBlock controlled, boolean testIsTrue) { diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index c7bdcb3169e..0a44ec3336b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -48,7 +48,7 @@ private class Argument extends Expr { */ class ArgumentNode extends Node { ArgumentNode() { - exists(Argument arg | this.asExpr() = arg) or + this.asExpr() instanceof Argument or this = getInstanceArgument(_) } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll index 35cf1974127..04e7376b11d 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Access.qll @@ -84,8 +84,8 @@ class VariableAccess extends Access, @varaccess { exists(Assignment a | a.getLValue() = this) or exists(CrementOperation c | c.getOperand() = this) or exists(AddressOfExpr addof | addof.getOperand() = this) or - exists(ReferenceToExpr rte | this.getConversion() = rte) or - exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) + this.getConversion() instanceof ReferenceToExpr or + this.getConversion() instanceof ArrayToPointerConversion } /** @@ -104,8 +104,8 @@ class VariableAccess extends Access, @varaccess { predicate isRValue() { not exists(AssignExpr ae | ae.getLValue() = this) and not exists(AddressOfExpr addof | addof.getOperand() = this) and - not exists(ReferenceToExpr rte | this.getConversion() = rte) and - not exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) + not this.getConversion() instanceof ReferenceToExpr and + not this.getConversion() instanceof ArrayToPointerConversion } /** @@ -218,9 +218,7 @@ class PointerFieldAccess extends FieldAccess { class DotFieldAccess extends FieldAccess { override string getAPrimaryQlClass() { result = "DotFieldAccess" } - DotFieldAccess() { - exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType()) - } + DotFieldAccess() { this.getQualifier().getFullyConverted().getUnspecifiedType() instanceof Class } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll index b4761dffe9a..7ceda8ddbff 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll @@ -35,7 +35,7 @@ class Call extends Expr, NameQualifiableElement, TCall { * * For example, `ptr->f()` has a qualifier, whereas plain `f()` does not. */ - predicate hasQualifier() { exists(Expr e | this.getChild(-1) = e) } + predicate hasQualifier() { exists(this.getChild(-1)) } /** * Gets the expression to the left of the function name or function pointer variable name. diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll index 273023a8229..701cfbfd636 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Cast.qll @@ -724,7 +724,7 @@ class SizeofOperator extends Expr, @runtime_sizeof { * ``` */ class SizeofExprOperator extends SizeofOperator { - SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) } + SizeofExprOperator() { exists(this.getChild(0)) } override string getAPrimaryQlClass() { result = "SizeofExprOperator" } @@ -787,7 +787,7 @@ class AlignofOperator extends Expr, @runtime_alignof { * ``` */ class AlignofExprOperator extends AlignofOperator { - AlignofExprOperator() { exists(Expr e | this.getChild(0) = e) } + AlignofExprOperator() { exists(this.getChild(0)) } /** * Gets the contained expression. diff --git a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll index 496e3f4511d..f1295169b5d 100644 --- a/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll +++ b/cpp/ql/lib/semmle/code/cpp/metrics/MetricClass.qll @@ -308,45 +308,45 @@ class MetricClass extends Class { } private string getAUsedHalsteadN1Operator() { - exists(CommaExpr e | e = this.getAnEnclosedExpression()) and result = "comma" + this.getAnEnclosedExpression() instanceof CommaExpr and result = "comma" or - exists(ReferenceToExpr e | e = this.getAnEnclosedExpression()) and result = "refTo" + this.getAnEnclosedExpression() instanceof ReferenceToExpr and result = "refTo" or - exists(PointerDereferenceExpr e | e = this.getAnEnclosedExpression()) and result = "dereference" + this.getAnEnclosedExpression() instanceof PointerDereferenceExpr and result = "dereference" or - exists(CStyleCast e | e = this.getAnEnclosedExpression()) and result = "cCast" + this.getAnEnclosedExpression() instanceof CStyleCast and result = "cCast" or - exists(StaticCast e | e = this.getAnEnclosedExpression()) and result = "staticCast" + this.getAnEnclosedExpression() instanceof StaticCast and result = "staticCast" or - exists(ConstCast e | e = this.getAnEnclosedExpression()) and result = "constCast" + this.getAnEnclosedExpression() instanceof ConstCast and result = "constCast" or - exists(ReinterpretCast e | e = this.getAnEnclosedExpression()) and result = "reinterpretCast" + this.getAnEnclosedExpression() instanceof ReinterpretCast and result = "reinterpretCast" or - exists(DynamicCast e | e = this.getAnEnclosedExpression()) and result = "dynamicCast" + this.getAnEnclosedExpression() instanceof DynamicCast and result = "dynamicCast" or - exists(SizeofExprOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofExpr" + this.getAnEnclosedExpression() instanceof SizeofExprOperator and result = "sizeofExpr" or - exists(SizeofTypeOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofType" + this.getAnEnclosedExpression() instanceof SizeofTypeOperator and result = "sizeofType" or - exists(IfStmt e | e = this.getAnEnclosedStmt()) and result = "ifVal" + this.getAnEnclosedStmt() instanceof IfStmt and result = "ifVal" or - exists(SwitchStmt e | e = this.getAnEnclosedStmt()) and result = "switchVal" + this.getAnEnclosedStmt() instanceof SwitchStmt and result = "switchVal" or - exists(ForStmt e | e = this.getAnEnclosedStmt()) and result = "forVal" + this.getAnEnclosedStmt() instanceof ForStmt and result = "forVal" or - exists(DoStmt e | e = this.getAnEnclosedStmt()) and result = "doVal" + this.getAnEnclosedStmt() instanceof DoStmt and result = "doVal" or - exists(WhileStmt e | e = this.getAnEnclosedStmt()) and result = "whileVal" + this.getAnEnclosedStmt() instanceof WhileStmt and result = "whileVal" or - exists(GotoStmt e | e = this.getAnEnclosedStmt()) and result = "gotoVal" + this.getAnEnclosedStmt() instanceof GotoStmt and result = "gotoVal" or - exists(ContinueStmt e | e = this.getAnEnclosedStmt()) and result = "continueVal" + this.getAnEnclosedStmt() instanceof ContinueStmt and result = "continueVal" or - exists(BreakStmt e | e = this.getAnEnclosedStmt()) and result = "breakVal" + this.getAnEnclosedStmt() instanceof BreakStmt and result = "breakVal" or - exists(ReturnStmt e | e = this.getAnEnclosedStmt()) and result = "returnVal" + this.getAnEnclosedStmt() instanceof ReturnStmt and result = "returnVal" or - exists(SwitchCase e | e = this.getAnEnclosedStmt()) and result = "caseVal" + this.getAnEnclosedStmt() instanceof SwitchCase and result = "caseVal" or exists(IfStmt s | s = this.getAnEnclosedStmt() and s.hasElse()) and result = "elseVal" diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll index 407c11834e5..c2dcce138c8 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll @@ -65,4 +65,6 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio } override predicate hasArrayOutput(int bufParam) { bufParam = 0 } + + override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll index d454257ea86..6b0a257d6f9 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll @@ -20,8 +20,9 @@ abstract class RemoteFlowSourceFunction extends Function { abstract predicate hasRemoteFlowSource(FunctionOutput output, string description); /** - * Holds if remote data from this source comes from a socket described by - * `input`. There is no result if a socket is not specified. + * Holds if remote data from this source comes from a socket or stream + * described by `input`. There is no result if none is specified by a + * parameter. */ predicate hasSocketInput(FunctionInput input) { none() } } @@ -59,8 +60,9 @@ abstract class RemoteFlowSinkFunction extends Function { abstract predicate hasRemoteFlowSink(FunctionInput input, string description); /** - * Holds if data put into this sink is transmitted through a socket described - * by `input`. There is no result if a socket is not specified. + * Holds if data put into this sink is transmitted through a socket or stream + * described by `input`. There is no result if none is specified by a + * parameter. */ predicate hasSocketInput(FunctionInput input) { none() } } diff --git a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll index c5c1903b4d1..3375383f2ea 100644 --- a/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll +++ b/cpp/ql/lib/semmle/code/cpp/padding/Padding.qll @@ -397,7 +397,7 @@ class PaddedType extends Class { // Support only single inheritance for now. If multiple inheritance is // supported, be sure to fix up the calls to getABaseClass*() to correctly // handle the presence of multiple base class subojects with the same type. - not exists(ClassDerivation cd | cd = this.getDerivation(1)) + not exists(this.getDerivation(1)) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll b/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll index a9802fad4b7..83b8c2936f0 100644 --- a/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll +++ b/cpp/ql/lib/semmle/code/cpp/pointsto/PointsTo.qll @@ -72,7 +72,7 @@ predicate lvalue(Element e) { or exists(Cast c | lvalue(c) and e.(Expr).getConversion() = c) or - exists(ReferenceToExpr toref | e.(Expr).getConversion() = toref) + e.(Expr).getConversion() instanceof ReferenceToExpr or // If f is a function-pointer, then the following two // calls are equivalent: f() and (*f)() diff --git a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll index ca9dd56436e..a980de9785d 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/BufferWrite.qll @@ -76,7 +76,7 @@ abstract class BufferWrite extends Expr { * can be found), specifying the reason for the estimation. */ int getMaxData(BufferWriteEstimationReason reason) { - reason instanceof UnspecifiedEstimateReason and result = getMaxData() + reason instanceof UnspecifiedEstimateReason and result = this.getMaxData() } /** @@ -85,7 +85,7 @@ abstract class BufferWrite extends Expr { * much smaller (8 bytes) than their true maximum length. This can be * helpful in determining the cause of a buffer overflow issue. */ - int getMaxDataLimited() { result = getMaxData() } + int getMaxDataLimited() { result = this.getMaxData() } /** * Gets an upper bound to the amount of data that's being written (if one @@ -94,7 +94,7 @@ abstract class BufferWrite extends Expr { * than their true maximum length. This can be helpful in determining the * cause of a buffer overflow issue. */ - int getMaxDataLimited(BufferWriteEstimationReason reason) { result = getMaxData(reason) } + int getMaxDataLimited(BufferWriteEstimationReason reason) { result = this.getMaxData(reason) } /** * Gets the size of a single character of the type this @@ -159,9 +159,11 @@ class StrCopyBW extends BufferWriteCall { this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } /** @@ -203,9 +205,11 @@ class StrCatBW extends BufferWriteCall { this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize() } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } /** @@ -269,9 +273,11 @@ class SprintfBW extends BufferWriteCall { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) { exists(FormatLiteral fl | @@ -281,10 +287,10 @@ class SprintfBW extends BufferWriteCall { } override int getMaxDataLimited(BufferWriteEstimationReason reason) { - result = getMaxDataLimitedImpl(reason) + result = this.getMaxDataLimitedImpl(reason) } - override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) } + override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) } } /** @@ -382,9 +388,11 @@ class SnprintfBW extends BufferWriteCall { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) { exists(FormatLiteral fl | @@ -394,10 +402,10 @@ class SnprintfBW extends BufferWriteCall { } override int getMaxDataLimited(BufferWriteEstimationReason reason) { - result = getMaxDataLimitedImpl(reason) + result = this.getMaxDataLimitedImpl(reason) } - override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) } + override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) } } /** @@ -495,9 +503,11 @@ class ScanfBW extends BufferWrite { ) } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } override string getBWDesc() { exists(FunctionCall fc | @@ -536,7 +546,9 @@ class RealpathBW extends BufferWriteCall { this = this // Suppress a compiler warning } - override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) } + override int getMaxData(BufferWriteEstimationReason reason) { + result = this.getMaxDataImpl(reason) + } - override int getMaxData() { result = max(getMaxDataImpl(_)) } + override int getMaxData() { result = max(this.getMaxDataImpl(_)) } } diff --git a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll index 00db6a18bcb..01230e6880c 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -258,7 +258,7 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) { format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = ["s", "S"] ) or - not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat()) + not c.(FormattingFunctionCall).getFormat() instanceof FormatLiteral or not c instanceof FormattingFunctionCall ) and diff --git a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll index af68daf025c..5b157a54ce8 100644 --- a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll @@ -271,7 +271,7 @@ class IfStmt extends ConditionalStmt, @stmt_if { * if (b) { x = 1; } * ``` */ - predicate hasElse() { exists(Stmt s | this.getElse() = s) } + predicate hasElse() { exists(this.getElse()) } override string toString() { result = "if (...) ... " } @@ -357,7 +357,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if { * if constexpr (b) { x = 1; } * ``` */ - predicate hasElse() { exists(Stmt s | this.getElse() = s) } + predicate hasElse() { exists(this.getElse()) } override string toString() { result = "if constexpr (...) ... " } diff --git a/cpp/ql/src/Critical/DeadCodeGoto.ql b/cpp/ql/src/Critical/DeadCodeGoto.ql index a2f8db771b0..425a39c74ca 100644 --- a/cpp/ql/src/Critical/DeadCodeGoto.ql +++ b/cpp/ql/src/Critical/DeadCodeGoto.ql @@ -30,8 +30,8 @@ where // the next statement isn't breaking out of a switch not s.(BreakStmt).getBreakable() instanceof SwitchStmt and // the next statement isn't a loop that can be jumped into - not exists(LabelStmt ls | s.(Loop).getStmt().getAChild*() = ls) and - not exists(SwitchCase sc | s.(Loop).getStmt().getAChild*() = sc) and + not s.(Loop).getStmt().getAChild*() instanceof LabelStmt and + not s.(Loop).getStmt().getAChild*() instanceof SwitchCase and // no preprocessor logic applies not functionContainsPreprocCode(js.getEnclosingFunction()) select js, "This statement makes $@ unreachable.", s, s.toString() diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index 29da7321603..719c16281f2 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -55,7 +55,7 @@ abstract class LeapYearFieldAccess extends YearFieldAccess { op.getAnOperand() = this and ( op instanceof AssignArithmeticOperation or - exists(BinaryArithmeticOperation bao | bao = op.getAnOperand()) or + op.getAnOperand() instanceof BinaryArithmeticOperation or op instanceof CrementOperation ) ) @@ -212,9 +212,7 @@ class ChecksForLeapYearFunctionCall extends FunctionCall { class LeapYearCheckConfiguration extends DataFlow::Configuration { LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" } - override predicate isSource(DataFlow::Node source) { - exists(VariableAccess va | va = source.asExpr()) - } + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess } override predicate isSink(DataFlow::Node sink) { exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument()) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql index ed378dce60a..025e50b246f 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql @@ -23,6 +23,10 @@ DeclStmt declWithNoInit(LocalVariable v) { not exists(v.getInitializer()) } +/** + * Control flow reachability from a buffer that is not not null terminated to a + * sink that requires null termination. + */ class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment { ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" } @@ -52,12 +56,44 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR override predicate isBarrier(ControlFlowNode node, StackVariable v) { exprDefinition(v, node, _) or - mayAddNullTerminator(node, v.getAnAccess()) or - node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken isSinkActual(node, v) // only report first use } } -from ImproperNullTerminationReachability r, LocalVariable v, VariableAccess va -where r.reaches(_, v, va) -select va, "Variable $@ may not be null terminated.", v, v.getName() +/** + * Flow from a place where null termination is added, to a sink of + * `ImproperNullTerminationReachability`. This was previously implemented as a + * simple barrier in `ImproperNullTerminationReachability`, but there were + * false positive results involving multiple paths from source to sink. We'd + * prefer to report only the results we are sure of. + */ +class NullTerminationReachability extends StackVariableReachabilityWithReassignment { + NullTerminationReachability() { this = "NullTerminationReachability" } + + override predicate isSourceActual(ControlFlowNode node, StackVariable v) { + mayAddNullTerminator(node, v.getAnAccess()) or // null termination + node.(AddressOfExpr).getOperand() = v.getAnAccess() // address taken (possible null termination) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable v) { + // have the same sinks as `ImproperNullTerminationReachability`. + exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v)) + } + + override predicate isBarrier(ControlFlowNode node, StackVariable v) { + // don't look further back than the source, or further forward than the sink + exists(ImproperNullTerminationReachability r | r.isSourceActual(node, v)) or + exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v)) + } +} + +from + ImproperNullTerminationReachability reaches, NullTerminationReachability nullTermReaches, + ControlFlowNode source, LocalVariable v, VariableAccess sink +where + reaches.reaches(source, v, sink) and + not exists(ControlFlowNode termination | + nullTermReaches.reaches(termination, _, sink) and + termination != source + ) +select sink, "Variable $@ may not be null terminated.", v, v.getName() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp index 00dfa215b33..bf9822d5fd8 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.cpp @@ -4,4 +4,4 @@ Record* fixRecord(Record* r) { myRecord.fix(); return &myRecord; //returns reference to myRecord, which is a stack-allocated object -} +} \ No newline at end of file diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql index f5dda53d484..3e68b7e3b0a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql @@ -3,7 +3,7 @@ * @description A function returns a pointer to a stack-allocated region of * memory. This memory is deallocated at the end of the function, * which may lead the caller to dereference a dangling pointer. - * @kind problem + * @kind path-problem * @id cpp/return-stack-allocated-memory * @problem.severity warning * @precision high @@ -12,59 +12,158 @@ */ import cpp -import semmle.code.cpp.dataflow.EscapesTree -import semmle.code.cpp.models.interfaces.PointerWrapper -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.IR +import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow -/** - * Holds if `n1` may flow to `n2`, ignoring flow through fields because these - * are currently modeled as an overapproximation that assumes all objects may - * alias. - */ -predicate conservativeDataFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - DataFlow::localFlowStep(n1, n2) and - not n2.asExpr() instanceof FieldAccess and - not hasNontrivialConversion(n2.asExpr()) +/** Holds if `f` has a name that we intrepret as evidence of intentionally returning the value of the stack pointer. */ +predicate intentionallyReturnsStackPointer(Function f) { + f.getName().toLowerCase().matches(["%stack%", "%sp%"]) } /** - * Holds if `e` has a conversion that changes it from lvalue to pointer or - * back. As the data-flow library does not support conversions, we cannot track - * data flow through such expressions. + * Holds if `source` is a node that represents the use of a stack variable */ -predicate hasNontrivialConversion(Expr e) { - e instanceof Conversion and - not ( - e instanceof Cast - or - e instanceof ParenthesisExpr +predicate isSource(Node source) { + exists(VariableAddressInstruction var, Function func | + var = source.asInstruction() and + func = var.getEnclosingFunction() and + var.getASTVariable() instanceof StackVariable and + // Pointer-to-member types aren't properly handled in the dbscheme. + not var.getResultType() instanceof PointerToMemberType and + // Rule out FPs caused by extraction errors. + not any(ErrorExpr e).getEnclosingFunction() = func and + not intentionallyReturnsStackPointer(func) ) - or - // A smart pointer can be stack-allocated while the data it points to is heap-allocated. - // So we exclude such "conversions" from this predicate. - e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction() - or - hasNontrivialConversion(e.getConversion()) } -from StackVariable var, VariableAccess va, ReturnStmt r -where - not var.getUnspecifiedType() instanceof ReferenceType and - not r.isFromUninstantiatedTemplate(_) and - va = var.getAnAccess() and +/** + * Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in + * a `ReturnValueInstruction`. We use the `StoreInstruction` instead of the instruction that defines the + * `ReturnValueInstruction`'s source value oprand because the former has better location information. + */ +predicate isSink(Node sink) { + exists(StoreInstruction store | + store.getDestinationAddress().(VariableAddressInstruction).getIRVariable() instanceof + IRReturnVariable and + sink.asOperand() = store.getSourceValueOperand() + ) +} + +/** Holds if `node1` _must_ flow to `node2`. */ +predicate step(Node node1, Node node2) { + instructionToOperandStep(node1.asInstruction(), node2.asOperand()) + or + operandToInstructionStep(node1.asOperand(), node2.asInstruction()) +} + +predicate instructionToOperandStep(Instruction instr, Operand operand) { operand.getDef() = instr } + +/** + * Holds if `operand` flows to the result of `instr`. + * + * This predicate ignores flow through `PhiInstruction`s to create a 'must flow' relation. It also + * intentionally conflates addresses of fields and their object, and pointer offsets with their + * base pointer as this allows us to detect cases where an object's address flows to a return statement + * via a field. For example: + * + * ```cpp + * struct S { int x, y }; + * int* test() { + * S s; + * return &s.x; // BAD: &s.x is an address of a variable on the stack. + * } + * ``` + */ +predicate operandToInstructionStep(Operand operand, Instruction instr) { + instr.(CopyInstruction).getSourceValueOperand() = operand + or + instr.(ConvertInstruction).getUnaryOperand() = operand + or + instr.(CheckedConvertOrNullInstruction).getUnaryOperand() = operand + or + instr.(InheritanceConversionInstruction).getUnaryOperand() = operand + or + instr.(FieldAddressInstruction).getObjectAddressOperand() = operand + or + instr.(PointerOffsetInstruction).getLeftOperand() = operand +} + +/** Holds if a source node flows to `n`. */ +predicate branchlessLocalFlow0(Node n) { + isSource(n) + or + exists(Node mid | + branchlessLocalFlow0(mid) and + step(mid, n) + ) +} + +/** Holds if `n` is reachable through some source node, and `n` also eventually reaches a sink. */ +predicate branchlessLocalFlow1(Node n) { + branchlessLocalFlow0(n) and ( - // To check if the address escapes directly from `e` in `return e`, we need - // to check the fully-converted `e` in case there are implicit - // array-to-pointer conversions or reference conversions. - variableAddressEscapesTree(va, r.getExpr().getFullyConverted()) + isSink(n) or - // The data flow library doesn't support conversions, so here we check that - // the address escapes into some expression `pointerToLocal`, which flows - // in one or more steps to a returned expression. - exists(Expr pointerToLocal | - variableAddressEscapesTree(va, pointerToLocal.getFullyConverted()) and - not hasNontrivialConversion(pointerToLocal) and - conservativeDataFlowStep+(DataFlow::exprNode(pointerToLocal), DataFlow::exprNode(r.getExpr())) + exists(Node mid | + branchlessLocalFlow1(mid) and + step(n, mid) ) ) -select r, "May return stack-allocated memory from $@.", va, va.toString() +} + +newtype TLocalPathNode = + TLocalPathNodeMid(Node n) { + branchlessLocalFlow1(n) and + ( + isSource(n) or + exists(LocalPathNodeMid mid | step(mid.getNode(), n)) + ) + } + +abstract class LocalPathNode extends TLocalPathNode { + Node n; + + /** Gets the underlying node. */ + Node getNode() { result = n } + + /** Gets a textual representation of this node. */ + string toString() { result = n.toString() } + + /** Gets the location of this element. */ + Location getLocation() { result = n.getLocation() } + + /** Gets a successor `LocalPathNode`, if any. */ + LocalPathNode getASuccessor() { step(this.getNode(), result.getNode()) } +} + +class LocalPathNodeMid extends LocalPathNode, TLocalPathNodeMid { + LocalPathNodeMid() { this = TLocalPathNodeMid(n) } +} + +class LocalPathNodeSink extends LocalPathNodeMid { + LocalPathNodeSink() { isSink(this.getNode()) } +} + +/** + * Holds if `source` is a source node, `sink` is a sink node, and there's flow + * from `source` to `sink` using `step` relation. + */ +predicate hasFlow(LocalPathNode source, LocalPathNodeSink sink) { + isSource(source.getNode()) and + source.getASuccessor+() = sink +} + +predicate reach(LocalPathNode n) { n instanceof LocalPathNodeSink or reach(n.getASuccessor()) } + +query predicate edges(LocalPathNode a, LocalPathNode b) { a.getASuccessor() = b and reach(b) } + +query predicate nodes(LocalPathNode n, string key, string val) { + reach(n) and key = "semmle.label" and val = n.toString() +} + +from LocalPathNode source, LocalPathNodeSink sink, VariableAddressInstruction var +where + hasFlow(source, sink) and + source.getNode().asInstruction() = var +select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAST(), + var.getAST().toString() diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 401ffc1b9d6..83ef373bd37 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -105,8 +105,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction { * practice it usually isn't very important which query reports a result as * long as its reported exactly once. * - * We do exclude function calls that specify a constant socket, which is - * likely to mean standard input, standard output or a similar channel. + * We do exclude function calls that specify an apparently constant socket, + * which is likely to mean standard input, standard output or a similar channel. */ abstract class NetworkSendRecv extends FunctionCall { SendRecv target; @@ -125,6 +125,13 @@ abstract class NetworkSendRecv extends FunctionCall { v.getInitializer().getExpr() instanceof Literal and g = globalValueNumber(v.getAnAccess()) ) + or + // result of a function call with literal inputs (likely constant) + exists(FunctionCall fc | + forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and + g = globalValueNumber(fc) + ) + // (this is far from exhaustive) ) ) } @@ -147,18 +154,28 @@ class NetworkRecv extends NetworkSendRecv { } /** - * An expression that is an argument or return value from an encryption or - * decryption call. + * An expression that is an argument or return value from an encryption / + * decryption call. This is quite inclusive to minimize false positives, for + * example `SecureZeroMemory` is not an encryption routine but a clue that + * encryption may be present. */ class Encrypted extends Expr { Encrypted() { exists(FunctionCall fc | - fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and + fc.getTarget() + .getName() + .toLowerCase() + .regexpMatch(".*(crypt|encode|decode|hash|securezero).*") and ( this = fc or this = fc.getAnArgument() ) ) + or + exists(Type t | + this.getType().refersTo(t) and + t.getName().toLowerCase().regexpMatch(".*(crypt|encode|decode|hash|securezero).*") + ) } } diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index bf673826347..81998bda450 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -34,9 +34,7 @@ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall { class NullDaclConfig extends DataFlow::Configuration { NullDaclConfig() { this = "NullDaclConfig" } - override predicate isSource(DataFlow::Node source) { - exists(NullValue nullExpr | source.asExpr() = nullExpr) - } + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } override predicate isSink(DataFlow::Node sink) { exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() | diff --git a/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md new file mode 100644 index 00000000000..19d5b950037 --- /dev/null +++ b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops. diff --git a/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md new file mode 100644 index 00000000000..4d89ad2eeaf --- /dev/null +++ b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results. \ No newline at end of file diff --git a/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md b/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md new file mode 100644 index 00000000000..ff51d88a94e --- /dev/null +++ b/cpp/ql/src/change-notes/2022-01-20-return-stack-allocated-memory.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The + query has also been converted to a `path-problem` query. \ No newline at end of file diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql index 4b147fa3612..106369e9319 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql @@ -24,10 +24,10 @@ class CallUsedToHandleErrors extends FunctionCall { not exists(this.(ControlFlowNode).getASuccessor()) or // call throwing an exception - exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr or // call logging a message, possibly an error - exists(FormattingFunction ff | ff = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof FormattingFunction or // enabling recursive search exists(CallUsedToHandleErrors fr | getTarget() = fr.getEnclosingFunction()) @@ -37,9 +37,9 @@ class CallUsedToHandleErrors extends FunctionCall { /** Holds if the conditions for a call outside the wrapper function are met. */ predicate conditionsOutsideWrapper(FunctionCall fcp) { fcp.getNumberOfArguments() > 0 and - not exists(ConditionalStmt cdtmp | fcp.getEnclosingStmt().getParentStmt*() = cdtmp) and - not exists(Loop lptmp | fcp.getEnclosingStmt().getParentStmt*() = lptmp) and - not exists(ReturnStmt rttmp | fcp.getEnclosingStmt().getParentStmt*() = rttmp) and + not fcp.getEnclosingStmt().getParentStmt*() instanceof ConditionalStmt and + not fcp.getEnclosingStmt().getParentStmt*() instanceof Loop and + not fcp.getEnclosingStmt().getParentStmt*() instanceof ReturnStmt and not exists(FunctionCall fctmp2 | fcp = fctmp2.getAnArgument().getAChild*()) and not exists(Assignment astmp | fcp = astmp.getRValue().getAChild*()) and not exists(Initializer intmp | fcp = intmp.getExpr().getAChild*()) and diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql index 72c7f359b47..22e42d39147 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql @@ -53,7 +53,15 @@ where fctmp.getTarget().hasGlobalOrStdName("fopen") or fctmp.getTarget().hasGlobalOrStdName("open") ) and - not fctmp.getArgument(1).getValue().matches("r%") and + ( + fctmp.getArgument(1).getValue().matches("%a%") or + fctmp.getArgument(1).getValue().matches("%w%") or + // unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes: + // https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491 + // this may introduce false negatives + fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT") or + fctmp.getArgument(1).getValueText().matches("%O_CREAT%") + ) and fctmp.getNumberOfArguments() = 2 and not fctmp.getArgument(0).getValue() = "/dev/null" and fcsnd = fctmp diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql b/cpp/ql/src/experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql index f08f7ef61f5..877b67cbbf8 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-377/InsecureTemporaryFile.ql @@ -92,7 +92,7 @@ where ) and exists(Variable vrtmp | vrtmp = fc.getArgument(0).(VariableAccess).getTarget() and - vrtmp = fctmp.getArgument(0).(AddressOfExpr).getAddressable().(Variable) and + vrtmp = fctmp.getArgument(0).(AddressOfExpr).getAddressable() and not vrtmp instanceof Field ) ) and diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql b/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql index 474f00acc55..7a884769bf8 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql @@ -26,7 +26,7 @@ class CallMayNotReturn extends FunctionCall { // call to another function that may not return exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction()) or - exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor()) + this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr } } @@ -127,7 +127,7 @@ predicate similarArguments(FunctionCall fc, FunctionCall fc1) { from FunctionCall fc, FunctionCall fc1 where - not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and + not fc.getASuccessor*() instanceof CallMayNotReturn and not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and ( // detecting a repeated call situation within one function diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql index 090eb0baa67..13d81cebf2b 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql @@ -15,6 +15,6 @@ from EqualityOperation e, PointerToMemberType t, Class c where e.getAnOperand().getType() = t and t.getClass() = c and - exists(VirtualFunction f | c.getAMemberFunction() = f) + c.getAMemberFunction() instanceof VirtualFunction select e, "AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected index 0325ba89a22..beaa1033eb2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected @@ -18,10 +18,6 @@ | test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 | | test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer | | test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer | -| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer | -| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer | -| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer | -| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer | | test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 | | test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer | | test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp index 88fbc46119b..49dc01a40df 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp @@ -352,7 +352,7 @@ void test_strlen(bool cond1, bool cond2) if (cond1) buffer[0] = 0; if (cond1) - strlen(buffer); // GOOD [FALSE POSITIVE] + strlen(buffer); // GOOD } { @@ -361,7 +361,7 @@ void test_strlen(bool cond1, bool cond2) if (cond1) buffer[0] = 0; if (cond2) - strlen(buffer); // BAD + strlen(buffer); // BAD [NOT DETECTED] } { @@ -389,7 +389,7 @@ void test_strlen(bool cond1, bool cond2) if (init != 0) { - strlen(buffer); // GOOD [FALSE POSITIVE] + strlen(buffer); // GOOD } } @@ -407,7 +407,7 @@ void test_strlen(bool cond1, bool cond2) { // ... } else { - strlen(buffer); // GOOD [FALSE POSITIVE] + strlen(buffer); // GOOD } } } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected index 59a9ee1322c..8f9d91fc1ad 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/ReturnStackAllocatedMemory.expected @@ -1,8 +1,231 @@ -| test.cpp:17:2:17:12 | return ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc | -| test.cpp:25:2:25:12 | return ... | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc | -| test.cpp:47:2:47:11 | return ... | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc | -| test.cpp:54:2:54:16 | return ... | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc | -| test.cpp:92:2:92:12 | return ... | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc | -| test.cpp:112:2:112:12 | return ... | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr | -| test.cpp:119:2:119:19 | return ... | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr | -| test.cpp:171:3:171:24 | return ... | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal | +edges +| test.cpp:17:9:17:11 | & ... | test.cpp:17:9:17:11 | StoreValue | +| test.cpp:17:10:17:11 | Unary | test.cpp:17:9:17:11 | & ... | +| test.cpp:17:10:17:11 | mc | test.cpp:17:10:17:11 | Unary | +| test.cpp:23:17:23:19 | & ... | test.cpp:23:17:23:19 | StoreValue | +| test.cpp:23:17:23:19 | Store | test.cpp:25:9:25:11 | Load | +| test.cpp:23:17:23:19 | StoreValue | test.cpp:23:17:23:19 | Store | +| test.cpp:23:18:23:19 | Unary | test.cpp:23:17:23:19 | & ... | +| test.cpp:23:18:23:19 | mc | test.cpp:23:18:23:19 | Unary | +| test.cpp:25:9:25:11 | Load | test.cpp:25:9:25:11 | ptr | +| test.cpp:25:9:25:11 | ptr | test.cpp:25:9:25:11 | StoreValue | +| test.cpp:39:17:39:18 | (reference to) | test.cpp:39:17:39:18 | StoreValue | +| test.cpp:39:17:39:18 | Store | test.cpp:41:10:41:12 | Load | +| test.cpp:39:17:39:18 | StoreValue | test.cpp:39:17:39:18 | Store | +| test.cpp:39:17:39:18 | Unary | test.cpp:39:17:39:18 | (reference to) | +| test.cpp:39:17:39:18 | mc | test.cpp:39:17:39:18 | Unary | +| test.cpp:41:9:41:12 | & ... | test.cpp:41:9:41:12 | StoreValue | +| test.cpp:41:10:41:12 | (reference dereference) | test.cpp:41:10:41:12 | Unary | +| test.cpp:41:10:41:12 | Load | test.cpp:41:10:41:12 | ref | +| test.cpp:41:10:41:12 | Unary | test.cpp:41:9:41:12 | & ... | +| test.cpp:41:10:41:12 | Unary | test.cpp:41:10:41:12 | (reference dereference) | +| test.cpp:41:10:41:12 | ref | test.cpp:41:10:41:12 | Unary | +| test.cpp:47:9:47:10 | (reference to) | test.cpp:47:9:47:10 | StoreValue | +| test.cpp:47:9:47:10 | Unary | test.cpp:47:9:47:10 | (reference to) | +| test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | Unary | +| test.cpp:54:9:54:15 | & ... | test.cpp:54:9:54:15 | StoreValue | +| test.cpp:54:11:54:12 | Unary | test.cpp:54:14:54:14 | a | +| test.cpp:54:11:54:12 | mc | test.cpp:54:11:54:12 | Unary | +| test.cpp:54:14:54:14 | Unary | test.cpp:54:9:54:15 | & ... | +| test.cpp:54:14:54:14 | a | test.cpp:54:14:54:14 | Unary | +| test.cpp:89:3:89:11 | Store | test.cpp:92:9:92:11 | Load | +| test.cpp:89:9:89:11 | & ... | test.cpp:89:9:89:11 | StoreValue | +| test.cpp:89:9:89:11 | StoreValue | test.cpp:89:3:89:11 | Store | +| test.cpp:89:10:89:11 | Unary | test.cpp:89:9:89:11 | & ... | +| test.cpp:89:10:89:11 | mc | test.cpp:89:10:89:11 | Unary | +| test.cpp:92:9:92:11 | Load | test.cpp:92:9:92:11 | ptr | +| test.cpp:92:9:92:11 | ptr | test.cpp:92:9:92:11 | StoreValue | +| test.cpp:112:9:112:11 | Unary | test.cpp:112:9:112:11 | array to pointer conversion | +| test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | Unary | +| test.cpp:112:9:112:11 | array to pointer conversion | test.cpp:112:9:112:11 | StoreValue | +| test.cpp:119:9:119:18 | & ... | test.cpp:119:9:119:18 | StoreValue | +| test.cpp:119:11:119:13 | Left | test.cpp:119:11:119:17 | access to array | +| test.cpp:119:11:119:13 | Unary | test.cpp:119:11:119:13 | array to pointer conversion | +| test.cpp:119:11:119:13 | arr | test.cpp:119:11:119:13 | Unary | +| test.cpp:119:11:119:13 | array to pointer conversion | test.cpp:119:11:119:13 | Left | +| test.cpp:119:11:119:17 | Unary | test.cpp:119:9:119:18 | & ... | +| test.cpp:119:11:119:17 | access to array | test.cpp:119:11:119:17 | Unary | +| test.cpp:134:2:134:14 | Store | test.cpp:135:2:135:4 | Load | +| test.cpp:134:8:134:10 | Left | test.cpp:134:8:134:14 | ... + ... | +| test.cpp:134:8:134:10 | Unary | test.cpp:134:8:134:10 | array to pointer conversion | +| test.cpp:134:8:134:10 | arr | test.cpp:134:8:134:10 | Unary | +| test.cpp:134:8:134:10 | array to pointer conversion | test.cpp:134:8:134:10 | Left | +| test.cpp:134:8:134:14 | ... + ... | test.cpp:134:8:134:14 | StoreValue | +| test.cpp:134:8:134:14 | StoreValue | test.cpp:134:2:134:14 | Store | +| test.cpp:135:2:135:4 | Left | test.cpp:135:2:135:6 | PointerAdd | +| test.cpp:135:2:135:4 | Load | test.cpp:135:2:135:4 | ptr | +| test.cpp:135:2:135:4 | ptr | test.cpp:135:2:135:4 | Left | +| test.cpp:135:2:135:6 | PointerAdd | test.cpp:135:2:135:6 | StoreValue | +| test.cpp:135:2:135:6 | Store | test.cpp:137:9:137:11 | Load | +| test.cpp:135:2:135:6 | StoreValue | test.cpp:135:2:135:6 | Store | +| test.cpp:137:9:137:11 | Load | test.cpp:137:9:137:11 | ptr | +| test.cpp:137:9:137:11 | ptr | test.cpp:137:9:137:11 | StoreValue | +| test.cpp:170:26:170:41 | (void *)... | test.cpp:170:26:170:41 | StoreValue | +| test.cpp:170:26:170:41 | Store | test.cpp:171:10:171:23 | Load | +| test.cpp:170:26:170:41 | StoreValue | test.cpp:170:26:170:41 | Store | +| test.cpp:170:34:170:41 | & ... | test.cpp:170:34:170:41 | Unary | +| test.cpp:170:34:170:41 | Unary | test.cpp:170:26:170:41 | (void *)... | +| test.cpp:170:35:170:41 | Unary | test.cpp:170:34:170:41 | & ... | +| test.cpp:170:35:170:41 | myLocal | test.cpp:170:35:170:41 | Unary | +| test.cpp:171:10:171:23 | Load | test.cpp:171:10:171:23 | pointerToLocal | +| test.cpp:171:10:171:23 | pointerToLocal | test.cpp:171:10:171:23 | StoreValue | +| test.cpp:176:25:176:34 | Store | test.cpp:177:10:177:23 | Load | +| test.cpp:176:25:176:34 | StoreValue | test.cpp:176:25:176:34 | Store | +| test.cpp:176:25:176:34 | Unary | test.cpp:176:25:176:34 | array to pointer conversion | +| test.cpp:176:25:176:34 | array to pointer conversion | test.cpp:176:25:176:34 | StoreValue | +| test.cpp:176:25:176:34 | localArray | test.cpp:176:25:176:34 | Unary | +| test.cpp:177:10:177:23 | (void *)... | test.cpp:177:10:177:23 | StoreValue | +| test.cpp:177:10:177:23 | Load | test.cpp:177:10:177:23 | pointerToLocal | +| test.cpp:177:10:177:23 | Unary | test.cpp:177:10:177:23 | (void *)... | +| test.cpp:177:10:177:23 | pointerToLocal | test.cpp:177:10:177:23 | Unary | +| test.cpp:182:21:182:27 | (reference to) | test.cpp:182:21:182:27 | StoreValue | +| test.cpp:182:21:182:27 | Store | test.cpp:183:10:183:19 | Load | +| test.cpp:182:21:182:27 | StoreValue | test.cpp:182:21:182:27 | Store | +| test.cpp:182:21:182:27 | Unary | test.cpp:182:21:182:27 | (reference to) | +| test.cpp:182:21:182:27 | myLocal | test.cpp:182:21:182:27 | Unary | +| test.cpp:183:10:183:19 | (reference dereference) | test.cpp:183:10:183:19 | Unary | +| test.cpp:183:10:183:19 | (reference to) | test.cpp:183:10:183:19 | StoreValue | +| test.cpp:183:10:183:19 | Load | test.cpp:183:10:183:19 | refToLocal | +| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference dereference) | +| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference to) | +| test.cpp:183:10:183:19 | refToLocal | test.cpp:183:10:183:19 | Unary | +| test.cpp:189:16:189:16 | (reference to) | test.cpp:189:16:189:16 | StoreValue | +| test.cpp:189:16:189:16 | Store | test.cpp:190:10:190:13 | Load | +| test.cpp:189:16:189:16 | StoreValue | test.cpp:189:16:189:16 | Store | +| test.cpp:189:16:189:16 | Unary | test.cpp:189:16:189:16 | (reference to) | +| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | Unary | +| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | Unary | +| test.cpp:190:10:190:13 | (reference to) | test.cpp:190:10:190:13 | StoreValue | +| test.cpp:190:10:190:13 | Load | test.cpp:190:10:190:13 | pRef | +| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference dereference) | +| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference to) | +| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | Unary | +nodes +| test.cpp:17:9:17:11 | & ... | semmle.label | & ... | +| test.cpp:17:9:17:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:17:10:17:11 | Unary | semmle.label | Unary | +| test.cpp:17:10:17:11 | mc | semmle.label | mc | +| test.cpp:23:17:23:19 | & ... | semmle.label | & ... | +| test.cpp:23:17:23:19 | Store | semmle.label | Store | +| test.cpp:23:17:23:19 | StoreValue | semmle.label | StoreValue | +| test.cpp:23:18:23:19 | Unary | semmle.label | Unary | +| test.cpp:23:18:23:19 | mc | semmle.label | mc | +| test.cpp:25:9:25:11 | Load | semmle.label | Load | +| test.cpp:25:9:25:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:25:9:25:11 | ptr | semmle.label | ptr | +| test.cpp:39:17:39:18 | (reference to) | semmle.label | (reference to) | +| test.cpp:39:17:39:18 | Store | semmle.label | Store | +| test.cpp:39:17:39:18 | StoreValue | semmle.label | StoreValue | +| test.cpp:39:17:39:18 | Unary | semmle.label | Unary | +| test.cpp:39:17:39:18 | mc | semmle.label | mc | +| test.cpp:41:9:41:12 | & ... | semmle.label | & ... | +| test.cpp:41:9:41:12 | StoreValue | semmle.label | StoreValue | +| test.cpp:41:10:41:12 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:41:10:41:12 | Load | semmle.label | Load | +| test.cpp:41:10:41:12 | Unary | semmle.label | Unary | +| test.cpp:41:10:41:12 | Unary | semmle.label | Unary | +| test.cpp:41:10:41:12 | ref | semmle.label | ref | +| test.cpp:47:9:47:10 | (reference to) | semmle.label | (reference to) | +| test.cpp:47:9:47:10 | StoreValue | semmle.label | StoreValue | +| test.cpp:47:9:47:10 | Unary | semmle.label | Unary | +| test.cpp:47:9:47:10 | mc | semmle.label | mc | +| test.cpp:54:9:54:15 | & ... | semmle.label | & ... | +| test.cpp:54:9:54:15 | StoreValue | semmle.label | StoreValue | +| test.cpp:54:11:54:12 | Unary | semmle.label | Unary | +| test.cpp:54:11:54:12 | mc | semmle.label | mc | +| test.cpp:54:14:54:14 | Unary | semmle.label | Unary | +| test.cpp:54:14:54:14 | a | semmle.label | a | +| test.cpp:89:3:89:11 | Store | semmle.label | Store | +| test.cpp:89:9:89:11 | & ... | semmle.label | & ... | +| test.cpp:89:9:89:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:89:10:89:11 | Unary | semmle.label | Unary | +| test.cpp:89:10:89:11 | mc | semmle.label | mc | +| test.cpp:92:9:92:11 | Load | semmle.label | Load | +| test.cpp:92:9:92:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:92:9:92:11 | ptr | semmle.label | ptr | +| test.cpp:112:9:112:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:112:9:112:11 | Unary | semmle.label | Unary | +| test.cpp:112:9:112:11 | arr | semmle.label | arr | +| test.cpp:112:9:112:11 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:119:9:119:18 | & ... | semmle.label | & ... | +| test.cpp:119:9:119:18 | StoreValue | semmle.label | StoreValue | +| test.cpp:119:11:119:13 | Left | semmle.label | Left | +| test.cpp:119:11:119:13 | Unary | semmle.label | Unary | +| test.cpp:119:11:119:13 | arr | semmle.label | arr | +| test.cpp:119:11:119:13 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:119:11:119:17 | Unary | semmle.label | Unary | +| test.cpp:119:11:119:17 | access to array | semmle.label | access to array | +| test.cpp:134:2:134:14 | Store | semmle.label | Store | +| test.cpp:134:8:134:10 | Left | semmle.label | Left | +| test.cpp:134:8:134:10 | Unary | semmle.label | Unary | +| test.cpp:134:8:134:10 | arr | semmle.label | arr | +| test.cpp:134:8:134:10 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:134:8:134:14 | ... + ... | semmle.label | ... + ... | +| test.cpp:134:8:134:14 | StoreValue | semmle.label | StoreValue | +| test.cpp:135:2:135:4 | Left | semmle.label | Left | +| test.cpp:135:2:135:4 | Load | semmle.label | Load | +| test.cpp:135:2:135:4 | ptr | semmle.label | ptr | +| test.cpp:135:2:135:6 | PointerAdd | semmle.label | PointerAdd | +| test.cpp:135:2:135:6 | Store | semmle.label | Store | +| test.cpp:135:2:135:6 | StoreValue | semmle.label | StoreValue | +| test.cpp:137:9:137:11 | Load | semmle.label | Load | +| test.cpp:137:9:137:11 | StoreValue | semmle.label | StoreValue | +| test.cpp:137:9:137:11 | ptr | semmle.label | ptr | +| test.cpp:170:26:170:41 | (void *)... | semmle.label | (void *)... | +| test.cpp:170:26:170:41 | Store | semmle.label | Store | +| test.cpp:170:26:170:41 | StoreValue | semmle.label | StoreValue | +| test.cpp:170:34:170:41 | & ... | semmle.label | & ... | +| test.cpp:170:34:170:41 | Unary | semmle.label | Unary | +| test.cpp:170:35:170:41 | Unary | semmle.label | Unary | +| test.cpp:170:35:170:41 | myLocal | semmle.label | myLocal | +| test.cpp:171:10:171:23 | Load | semmle.label | Load | +| test.cpp:171:10:171:23 | StoreValue | semmle.label | StoreValue | +| test.cpp:171:10:171:23 | pointerToLocal | semmle.label | pointerToLocal | +| test.cpp:176:25:176:34 | Store | semmle.label | Store | +| test.cpp:176:25:176:34 | StoreValue | semmle.label | StoreValue | +| test.cpp:176:25:176:34 | Unary | semmle.label | Unary | +| test.cpp:176:25:176:34 | array to pointer conversion | semmle.label | array to pointer conversion | +| test.cpp:176:25:176:34 | localArray | semmle.label | localArray | +| test.cpp:177:10:177:23 | (void *)... | semmle.label | (void *)... | +| test.cpp:177:10:177:23 | Load | semmle.label | Load | +| test.cpp:177:10:177:23 | StoreValue | semmle.label | StoreValue | +| test.cpp:177:10:177:23 | Unary | semmle.label | Unary | +| test.cpp:177:10:177:23 | pointerToLocal | semmle.label | pointerToLocal | +| test.cpp:182:21:182:27 | (reference to) | semmle.label | (reference to) | +| test.cpp:182:21:182:27 | Store | semmle.label | Store | +| test.cpp:182:21:182:27 | StoreValue | semmle.label | StoreValue | +| test.cpp:182:21:182:27 | Unary | semmle.label | Unary | +| test.cpp:182:21:182:27 | myLocal | semmle.label | myLocal | +| test.cpp:183:10:183:19 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:183:10:183:19 | (reference to) | semmle.label | (reference to) | +| test.cpp:183:10:183:19 | Load | semmle.label | Load | +| test.cpp:183:10:183:19 | StoreValue | semmle.label | StoreValue | +| test.cpp:183:10:183:19 | Unary | semmle.label | Unary | +| test.cpp:183:10:183:19 | Unary | semmle.label | Unary | +| test.cpp:183:10:183:19 | refToLocal | semmle.label | refToLocal | +| test.cpp:189:16:189:16 | (reference to) | semmle.label | (reference to) | +| test.cpp:189:16:189:16 | Store | semmle.label | Store | +| test.cpp:189:16:189:16 | StoreValue | semmle.label | StoreValue | +| test.cpp:189:16:189:16 | Unary | semmle.label | Unary | +| test.cpp:189:16:189:16 | p | semmle.label | p | +| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) | +| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) | +| test.cpp:190:10:190:13 | Load | semmle.label | Load | +| test.cpp:190:10:190:13 | StoreValue | semmle.label | StoreValue | +| test.cpp:190:10:190:13 | Unary | semmle.label | Unary | +| test.cpp:190:10:190:13 | Unary | semmle.label | Unary | +| test.cpp:190:10:190:13 | pRef | semmle.label | pRef | +#select +| test.cpp:17:9:17:11 | StoreValue | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc | +| test.cpp:25:9:25:11 | StoreValue | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc | +| test.cpp:41:9:41:12 | StoreValue | test.cpp:39:17:39:18 | mc | test.cpp:41:9:41:12 | StoreValue | May return stack-allocated memory from $@. | test.cpp:39:17:39:18 | mc | mc | +| test.cpp:47:9:47:10 | StoreValue | test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | StoreValue | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc | +| test.cpp:54:9:54:15 | StoreValue | test.cpp:54:11:54:12 | mc | test.cpp:54:9:54:15 | StoreValue | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc | +| test.cpp:92:9:92:11 | StoreValue | test.cpp:89:10:89:11 | mc | test.cpp:92:9:92:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc | +| test.cpp:112:9:112:11 | StoreValue | test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr | +| test.cpp:119:9:119:18 | StoreValue | test.cpp:119:11:119:13 | arr | test.cpp:119:9:119:18 | StoreValue | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr | +| test.cpp:137:9:137:11 | StoreValue | test.cpp:134:8:134:10 | arr | test.cpp:137:9:137:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:134:8:134:10 | arr | arr | +| test.cpp:171:10:171:23 | StoreValue | test.cpp:170:35:170:41 | myLocal | test.cpp:171:10:171:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal | +| test.cpp:177:10:177:23 | StoreValue | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray | +| test.cpp:183:10:183:19 | StoreValue | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | StoreValue | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal | +| test.cpp:190:10:190:13 | StoreValue | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | StoreValue | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp index 1ce2558a34f..a1726169654 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ReturnStackAllocatedMemory/test.cpp @@ -38,7 +38,7 @@ MyClass *test4() MyClass mc; MyClass &ref = mc; - return &ref; // BAD [NOT DETECTED] + return &ref; // BAD } MyClass &test5() @@ -134,7 +134,7 @@ char *testArray4() ptr = arr + 1; ptr++; - return ptr; // BAD [NOT DETECTED] + return ptr; // BAD } char *testArray5() @@ -174,20 +174,20 @@ void *conversionBeforeDataFlow() { void *arrayConversionBeforeDataFlow() { int localArray[4]; int *pointerToLocal = localArray; // has conversion - return pointerToLocal; // BAD [NOT DETECTED] + return pointerToLocal; // BAD } int &dataFlowThroughReference() { int myLocal; int &refToLocal = myLocal; // has conversion - return refToLocal; // BAD [NOT DETECTED] + return refToLocal; // BAD } int *&conversionInFlow() { int myLocal; int *p = &myLocal; int *&pRef = p; // has conversion in the middle of data flow - return pRef; // BAD [NOT DETECTED] + return pRef; // BAD } namespace std { @@ -215,4 +215,9 @@ auto make_read_port() auto port = std::shared_ptr(new int); auto ptr = port.get(); return ptr; // GOOD +} + +void* get_sp() { + int p; + return (void*)&p; // GOOD: The function name makes it sound like the programmer intended to get the value of the stack pointer. } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 354ccf9eb53..02d2773348c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -37,10 +37,8 @@ edges | test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password | | test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr | | test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr | -| test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | -| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | | test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 | | test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer | | test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 | @@ -84,6 +82,13 @@ edges | test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password | | test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace | | test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password | +| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | +| test3.cpp:366:8:366:15 | password | test3.cpp:374:3:374:18 | call to SecureZeroBuffer | +| test3.cpp:366:8:366:15 | password | test3.cpp:374:20:374:27 | password | +| test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | +| test3.cpp:398:18:398:25 | password | test3.cpp:400:15:400:23 | & ... | +| test3.cpp:398:18:398:25 | password | test3.cpp:400:16:400:23 | password | +| test3.cpp:398:18:398:25 | password | test3.cpp:400:33:400:40 | password | | test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt | | test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword | | test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt | @@ -144,11 +149,9 @@ nodes | test3.cpp:217:30:217:37 | password | semmle.label | password | | test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr | | test3.cpp:225:34:225:41 | password | semmle.label | password | -| test3.cpp:227:22:227:29 | password | semmle.label | password | | test3.cpp:228:26:228:33 | password | semmle.label | password | | test3.cpp:239:7:239:14 | password | semmle.label | password | | test3.cpp:241:8:241:15 | password | semmle.label | password | -| test3.cpp:242:8:242:15 | password | semmle.label | password | | test3.cpp:252:8:252:16 | password1 | semmle.label | password1 | | test3.cpp:252:24:252:32 | password2 | semmle.label | password2 | | test3.cpp:254:15:254:23 | password1 | semmle.label | password1 | @@ -195,6 +198,16 @@ nodes | test3.cpp:352:16:352:23 | password | semmle.label | password | | test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace | | test3.cpp:353:20:353:27 | password | semmle.label | password | +| test3.cpp:366:8:366:15 | password | semmle.label | password | +| test3.cpp:368:15:368:22 | password | semmle.label | password | +| test3.cpp:374:3:374:18 | call to SecureZeroBuffer | semmle.label | call to SecureZeroBuffer | +| test3.cpp:374:20:374:27 | password | semmle.label | password | +| test3.cpp:386:8:386:15 | password | semmle.label | password | +| test3.cpp:388:15:388:22 | password | semmle.label | password | +| test3.cpp:398:18:398:25 | password | semmle.label | password | +| test3.cpp:400:15:400:23 | & ... | semmle.label | & ... | +| test3.cpp:400:16:400:23 | password | semmle.label | password | +| test3.cpp:400:33:400:40 | password | semmle.label | password | | test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! | | test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt | | test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword | @@ -218,11 +231,10 @@ subpaths | test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:129:39:129:47 | password1 | password1 | | test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:126:9:126:23 | global_password | global_password | | test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password | -| test3.cpp:227:2:227:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password | | test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password | | test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password | -| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password | | test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:268:19:268:26 | password | password | | test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 | | test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 | | test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password | +| test3.cpp:388:3:388:6 | call to recv | test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:386:8:386:15 | password | password | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 15e314566d1..bac96324554 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -224,7 +224,7 @@ int get_socket(int from); void test_more_stdio(const char *password) { - send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output [FALSE POSITIVE] + send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output send(get_socket(val()), password, 128, val()); // BAD } @@ -239,7 +239,7 @@ void test_fgets(FILE *stream) char password[128]; fgets(password, 128, stream); // BAD - fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input [FALSE POSITIVE] + fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input } void encrypt_to_buffer(const char *input, char* output); @@ -356,3 +356,68 @@ void test_loops() } } } + +void DoDisguisedOperation(char *buffer, size_t size); +void SecureZeroBuffer(char *buffer, size_t size); + +void test_securezero() +{ + { + char password[256]; + + recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted + + DoDisguisedOperation(password, 256); // decryption (disguised) + + // ... + + SecureZeroBuffer(password, 256); // evidence we may have been doing decryption + } +} + +struct encrypted_data +{ + char data[256]; +}; + +void test_more_clues() +{ + { + char password[256]; + + recv(val(), password, 256, val()); // BAD: not encrypted + } + + { + char encrypted_password[256]; + + recv(val(), encrypted_password, 256, val()); // GOOD: password is (probably) encrypted + } + + { + encrypted_data password; + + recv(val(), &password, sizeof(password), val()); // GOOD: password is (probably) encrypted + } +} + +struct packet +{ + char password[256]; +}; + +void test_member_password() +{ + { + packet p; + + recv(val(), p.password, 256, val()); // BAD: not encrypted [NOT DETECTED] + } + + { + packet p; + + recv(val(), p.password, 256, val()); // GOOD: password is encrypted + decrypt_inplace(p.password); // proof that `password` was in fact encrypted + } +} diff --git a/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme new file mode 100644 index 00000000000..ff083666c7f --- /dev/null +++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme @@ -0,0 +1,2098 @@ +/* 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); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +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_global( + unique int id: @using_directive ref +); + +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, 3: span */ + +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_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int 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/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..193c35b0e37 --- /dev/null +++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme @@ -0,0 +1,2088 @@ +/* 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); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +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_global( + unique int id: @using_directive ref +); + +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/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties new file mode 100644 index 00000000000..47cd8720ce9 --- /dev/null +++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties @@ -0,0 +1,5 @@ +description: Remove support for line span pragma. +compatibility: backwards +directive_line_offset.rel: delete +directive_line_span.rel: delete + diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs index 75405d562fe..773d43e40f0 100644 --- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs +++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs @@ -6,6 +6,7 @@ using System.Reflection.Metadata; using System.Reflection; using System.Runtime.InteropServices; using System.Globalization; +using Semmle.Util; using Semmle.Util.Logging; namespace Semmle.Extraction.CIL.Driver @@ -169,18 +170,13 @@ namespace Semmle.Extraction.CIL.Driver /// /// Parses the command line and collates a list of DLLs/EXEs to extract. /// - internal class ExtractorOptions + internal class ExtractorOptions : CommonOptions { private readonly AssemblyList assemblyList = new AssemblyList(); public ExtractorOptions(string[] args) { - Verbosity = Verbosity.Info; - Threads = System.Environment.ProcessorCount; - PDB = true; - TrapCompression = TrapWriter.CompressionMode.Gzip; - - ParseArgs(args); + this.ParseArguments(args.Append("--pdb").ToArray()); AddFrameworkDirectories(false); @@ -203,12 +199,6 @@ namespace Semmle.Extraction.CIL.Driver AddDirectory(RuntimeEnvironment.GetRuntimeDirectory(), extractAll); } - public Verbosity Verbosity { get; private set; } - public bool NoCache { get; private set; } - public int Threads { get; private set; } - public bool PDB { get; private set; } - public TrapWriter.CompressionMode TrapCompression { get; private set; } - private void AddFileOrDirectory(string path) { path = Path.GetFullPath(path); @@ -237,43 +227,25 @@ namespace Semmle.Extraction.CIL.Driver /// public IEnumerable MissingReferences => assemblyList.MissingReferences; - private void ParseArgs(string[] args) + public override bool HandleFlag(string flag, bool value) { - foreach (var arg in args) + switch (flag) { - if (arg == "--verbose") - { - Verbosity = Verbosity.All; - } - else if (arg == "--silent") - { - Verbosity = Verbosity.Off; - } - else if (arg.StartsWith("--verbosity:")) - { - Verbosity = (Verbosity)int.Parse(arg.Substring(12)); - } - else if (arg == "--dotnet") - { - AddFrameworkDirectories(true); - } - else if (arg == "--nocache") - { - NoCache = true; - } - else if (arg.StartsWith("--threads:")) - { - Threads = int.Parse(arg.Substring(10)); - } - else if (arg == "--no-pdb") - { - PDB = false; - } - else - { - AddFileOrDirectory(arg); - } + case "dotnet": + if (value) + AddFrameworkDirectories(true); + return true; + default: + return base.HandleFlag(flag, value); } } + + public override bool HandleArgument(string argument) + { + AddFileOrDirectory(argument); + return true; + } + + public override void InvalidArgument(string argument) { } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs index 940cd647ed8..9e72f560854 100644 --- a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs @@ -20,11 +20,11 @@ namespace Semmle.Extraction.CIL.Driver Console.WriteLine(" path A directory/dll/exe to analyze"); } - private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression) + private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, CommonOptions options) { var sw = new Stopwatch(); sw.Start(); - Analyser.ExtractCIL(layout, assemblyPath, logger, nocache, extractPdbs, trapCompression, out _, out _); + Analyser.ExtractCIL(layout, assemblyPath, logger, options, out _, out _); sw.Stop(); logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed); } @@ -43,8 +43,7 @@ namespace Semmle.Extraction.CIL.Driver var actions = options.AssembliesToExtract .Select(asm => asm.Filename) - .Select(filename => - () => ExtractAssembly(layout, filename, logger, options.NoCache, options.PDB, options.TrapCompression)) + .Select(filename => () => ExtractAssembly(layout, filename, logger, options)) .ToArray(); foreach (var missingRef in options.MissingReferences) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs index d93d7eb7dc7..e78843148af 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs @@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL /// Whether to extract PDBs. /// The path of the trap file. /// Whether the file was extracted (false=cached). - public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression, out string trapFile, out bool extracted) + public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, CommonOptions options, out string trapFile, out bool extracted) { trapFile = ""; extracted = false; @@ -33,14 +33,14 @@ namespace Semmle.Extraction.CIL { var canonicalPathCache = CanonicalPathCache.Create(logger, 1000); var pathTransformer = new PathTransformer(canonicalPathCache); - var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer); + var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer, options); var transformedAssemblyPath = pathTransformer.Transform(assemblyPath); var project = layout.LookupProjectOrDefault(transformedAssemblyPath); - using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), trapCompression, discardDuplicates: true); + using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), options.TrapCompression, discardDuplicates: true); trapFile = trapWriter.TrapFile; - if (nocache || !System.IO.File.Exists(trapFile)) + if (!options.Cache || !System.IO.File.Exists(trapFile)) { - ExtractCIL(extractor, trapWriter, extractPdbs); + ExtractCIL(extractor, trapWriter, options.PDB); extracted = true; } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs index 45623b3ceeb..29eb7d118ff 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs @@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL.Entities else Context.TrapWriter.Archive(TransformedPath, text); - yield return Tuples.file_extraction_mode(this, 2); + yield return Tuples.file_extraction_mode(this, Context.Extractor.Mode | ExtractorMode.Pdb); } } } diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs index d58647aba77..44519f45468 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs @@ -206,7 +206,7 @@ namespace Semmle.Extraction.CIL internal static Tuple files(File file, string fullName) => new Tuple("files", file, fullName); - internal static Tuple file_extraction_mode(File file, int mode) => + internal static Tuple file_extraction_mode(File file, ExtractorMode mode) => new Tuple("file_extraction_mode", file, mode); internal static Tuple folders(Folder folder, string path) => diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs index 9555fabec4f..043f8dbf664 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs @@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities public static Assembly CreateOutputAssembly(Context cx) { - if (cx.Extractor.Standalone) + if (cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone)) throw new InternalError("Attempting to create the output assembly in standalone extraction mode"); return AssemblyConstructorFactory.Instance.CreateEntity(cx, outputAssemblyCacheKey, null); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs index 7e7fc39aab8..a1b976c4a6c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities if (attributeSyntax is not null) { - if (!Context.Extractor.Standalone) + if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone)) { trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context)); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs index 378bda881f7..e03f945175b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs @@ -85,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities { // Some built in operators lack locations, so loc is null. yield return Context.CreateLocation(ReportingLocation); - if (!Context.Extractor.Standalone && loc.Kind == LocationKind.SourceFile) + if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && loc.Kind == LocationKind.SourceFile) yield return Assembly.CreateOutputAssembly(Context); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs index a50b68f75b7..1af93bfe25c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs @@ -129,7 +129,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions .Where(method => method.Parameters.Length >= Syntax.ArgumentList.Arguments.Count) .Where(method => method.Parameters.Count(p => !p.HasExplicitDefaultValue) <= Syntax.ArgumentList.Arguments.Count); - return Context.Extractor.Standalone ? + return Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) ? candidates.FirstOrDefault() : candidates.SingleOrDefault(); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs index fae77b033ad..5d43a7f89d3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs @@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities } } - trapFile.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0); + trapFile.file_extraction_mode(this, Context.Extractor.Mode); } private bool IsPossiblyTextFile() diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs index 3d6cb01837e..a94f0b54747 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs @@ -111,6 +111,9 @@ namespace Semmle.Extraction.CSharp.Entities if (nt is null) throw new InternalError(symbol, "Symbol kind is inconsistent with its type"); + if (nt.IsRecord) + HasModifier(cx, trapFile, key, "record"); + if (nt.TypeKind == TypeKind.Struct) { if (nt.IsReadOnly) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs index 6afae54a129..8f28b97155c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs @@ -5,36 +5,28 @@ using System.IO; namespace Semmle.Extraction.CSharp.Entities { - internal class LineDirective : PreprocessorDirective + internal class LineDirective : LineOrSpanDirective { private LineDirective(Context cx, LineDirectiveTriviaSyntax trivia) - : base(cx, trivia) + : base(cx, trivia, trivia.Line.Kind() switch + { + SyntaxKind.DefaultKeyword => LineDirectiveKind.Default, + SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden, + SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric, + _ => throw new InternalError(trivia, "Unhandled line token kind") + }) { } protected override void PopulatePreprocessor(TextWriter trapFile) { - var type = Symbol.Line.Kind() switch - { - SyntaxKind.DefaultKeyword => 0, - SyntaxKind.HiddenKeyword => 1, - SyntaxKind.NumericLiteralToken => 2, - _ => throw new InternalError(Symbol, "Unhandled line token kind") - }; - - trapFile.directive_lines(this, type); - if (Symbol.Line.IsKind(SyntaxKind.NumericLiteralToken)) { var value = (int)Symbol.Line.Value!; trapFile.directive_line_value(this, value); - - if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText)) - { - var file = File.Create(Context, Symbol.File.ValueText); - trapFile.directive_line_file(this, file); - } } + + base.PopulatePreprocessor(trapFile); } public static LineDirective Create(Context cx, LineDirectiveTriviaSyntax line) => diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs new file mode 100644 index 00000000000..20b9ff22a0b --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs @@ -0,0 +1,37 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal enum LineDirectiveKind + { + Default = 0, + Hidden = 1, + Numeric = 2, + Span = 3 + } + + internal abstract class LineOrSpanDirective : PreprocessorDirective where T : LineOrSpanDirectiveTriviaSyntax + { + private readonly LineDirectiveKind kind; + + protected LineOrSpanDirective(Context cx, T trivia, LineDirectiveKind k) + : base(cx, trivia) + { + kind = k; + } + + protected override void PopulatePreprocessor(TextWriter trapFile) + { + trapFile.directive_lines(this, kind); + + if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText)) + { + var file = File.Create(Context, Symbol.File.ValueText); + trapFile.directive_line_file(this, file); + } + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs new file mode 100644 index 00000000000..9f21204731e --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs @@ -0,0 +1,39 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System.IO; + +namespace Semmle.Extraction.CSharp.Entities +{ + internal class LineSpanDirective : LineOrSpanDirective + { + private LineSpanDirective(Context cx, LineSpanDirectiveTriviaSyntax trivia) + : base(cx, trivia, LineDirectiveKind.Span) { } + + public static LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax line) => + LineSpanDirectiveFactory.Instance.CreateEntity(cx, line, line); + + protected override void PopulatePreprocessor(TextWriter trapFile) + { + var startLine = (int)Symbol.Start.Line.Value!; + var startColumn = (int)Symbol.Start.Character.Value!; + var endLine = (int)Symbol.End.Line.Value!; + var endColumn = (int)Symbol.End.Character.Value!; + trapFile.directive_line_span(this, startLine, startColumn, endLine, endColumn); + + if (Symbol.CharacterOffset.Value is int offset) + { + trapFile.directive_line_offset(this, offset); + } + + base.PopulatePreprocessor(trapFile); + } + + private class LineSpanDirectiveFactory : CachedEntityFactory + { + public static LineSpanDirectiveFactory Instance { get; } = new LineSpanDirectiveFactory(); + + public override LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax init) => new(cx, init); + } + } +} \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs index dba00d61207..a5337bf836c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs @@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.preprocessor_directive_active(this, Symbol.IsActive); trapFile.preprocessor_directive_location(this, Context.CreateLocation(ReportingLocation)); - if (!Context.Extractor.Standalone) + if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone)) { var compilation = Compilation.Create(Context); trapFile.preprocessor_directive_compilation(this, compilation); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs index 08a1fa3eb0f..b23ba8ced26 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs @@ -90,7 +90,11 @@ namespace Semmle.Extraction.CSharp.Entities var tts = (TupleTypeSyntax)syntax; var tt = (TupleType)type; Emit(trapFile, loc ?? syntax.GetLocation(), parent, type); - tts.Elements.Zip(tt.TupleElements, (s, t) => Create(Context, s.Type, this, t.Type)).Enumerate(); + foreach (var (s, t) in tts.Elements.Zip(tt.TupleElements, (s, t) => (s, t?.Type))) + { + if (t is not null) + Create(Context, s.Type, this, t); + } return; case SyntaxKind.GenericName: Emit(trapFile, loc ?? syntax.GetLocation(), parent, type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 06c6ccee9a8..e412aa7809d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -108,7 +108,7 @@ namespace Semmle.Extraction.CSharp.Entities foreach (var l in GetLocations(Symbol)) yield return Context.CreateLocation(l); - if (!Context.Extractor.Standalone && Symbol.DeclaringSyntaxReferences.Any()) + if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && Symbol.DeclaringSyntaxReferences.Any()) yield return Assembly.CreateOutputAssembly(Context); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index 56db07671d7..f25016b6f59 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init) { - tupleElementsLazy = new Lazy(() => Symbol.TupleElements.Select(t => Field.Create(cx, t)).ToArray()); + tupleElementsLazy = new Lazy(() => Symbol.GetTupleElementsMaybeNull().Select(t => t is null ? null : Field.Create(cx, t)).ToArray()); } // All tuple types are "local types" @@ -47,7 +47,10 @@ namespace Semmle.Extraction.CSharp.Entities var index = 0; foreach (var element in TupleElements) - trapFile.tuple_element(this, index++, element); + { + if (element is not null) + trapFile.tuple_element(this, index++, element); + } // Note: symbol.Locations seems to be very inconsistent // about what locations are available for a tuple type. @@ -56,9 +59,10 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.type_location(this, Context.CreateLocation(l)); } - private readonly Lazy tupleElementsLazy; - public Field[] TupleElements => tupleElementsLazy.Value; + private readonly Lazy tupleElementsLazy; + public Field?[] TupleElements => tupleElementsLazy.Value; - public override IEnumerable TypeMentions => TupleElements.Select(e => e.Type); + public override IEnumerable TypeMentions => + TupleElements.OfType().Select(e => e.Type); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs index 907948f2408..336a76ffbdc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs @@ -178,7 +178,7 @@ namespace Semmle.Extraction.CSharp { var stopwatch = new Stopwatch(); stopwatch.Start(); - CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, !options.Cache, options.PDB, options.TrapCompression, out var trapFile, out var extracted); + CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, options, out var trapFile, out var extracted); stopwatch.Stop(); ReportProgress(r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs index 23661234f98..9173ab35217 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs @@ -15,7 +15,7 @@ namespace Semmle.Extraction.CSharp { compilation = compilationIn; layout = new Layout(); - extractor = new StandaloneExtractor(Logger, PathTransformer); + extractor = new StandaloneExtractor(Logger, PathTransformer, options); this.options = options; LogExtractorInfo(Extraction.Extractor.Version); SetReferencePaths(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs index 133148723fa..4c15d053a93 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs @@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp this.layout = new Layout(); this.options = options; this.compilation = compilation; - this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer); + this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer, options); LogDiagnostics(); SetReferencePaths(); @@ -188,7 +188,7 @@ namespace Semmle.Extraction.CSharp { get { - return extractor is null || extractor.Standalone || compilation is null ? Enumerable.Empty() : + return extractor is null || extractor.Mode.HasFlag(ExtractorMode.Standalone) || compilation is null ? Enumerable.Empty() : compilation. GetDiagnostics(). Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id)); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs index 49b1e96990a..9df04a7cfa5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs @@ -17,50 +17,35 @@ namespace Semmle.Extraction.CSharp.Populators /// public IEnumerable BranchesTaken => branchesTaken; - public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia) - { + public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia) => this.cx = cx; - } - public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) - { + public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) => Entities.PragmaWarningDirective.Create(cx, node); - } - public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) - { + public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) => Entities.PragmaChecksumDirective.Create(cx, node); - } - public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) - { + public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) => Entities.DefineDirective.Create(cx, node); - } - public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) - { + public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) => Entities.UndefineDirective.Create(cx, node); - } - public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node) - { + public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node) => Entities.WarningDirective.Create(cx, node); - } - public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node) - { + public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node) => Entities.ErrorDirective.Create(cx, node); - } - public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) - { + public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) => Entities.NullableDirective.Create(cx, node); - } - public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) - { + public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) => Entities.LineDirective.Create(cx, node); - } + + public override void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) => + Entities.LineSpanDirective.Create(cx, node); private readonly Stack regionStarts = new Stack(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs index f49a57398ea..0b60fd4fcf0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs @@ -82,7 +82,7 @@ namespace Semmle.Extraction.CSharp.Populators public override void VisitAttributeList(AttributeListSyntax node) { - if (Cx.Extractor.Standalone) + if (Cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone)) return; var outputAssembly = Assembly.CreateOutputAssembly(Cx); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 72ecf842959..26a104286a8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -280,17 +280,30 @@ namespace Semmle.Extraction.CSharp private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) => BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined)); + /// + /// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943 + /// + public static IEnumerable GetTupleElementsMaybeNull(this INamedTypeSymbol type) => + type.TupleElements; + private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType) { if (!constructUnderlyingTupleType && named.IsTupleType) { trapFile.Write('('); - trapFile.BuildList(",", named.TupleElements, - f => + trapFile.BuildList(",", named.GetTupleElementsMaybeNull(), + (i, f) => { - trapFile.Write((f.CorrespondingTupleField ?? f).Name); - trapFile.Write(":"); - f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false); + if (f is null) + { + trapFile.Write($"null({i})"); + } + else + { + trapFile.Write((f.CorrespondingTupleField ?? f).Name); + trapFile.Write(":"); + f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false); + } } ); trapFile.Write(")"); @@ -464,8 +477,14 @@ namespace Semmle.Extraction.CSharp trapFile.Write('('); trapFile.BuildList( ",", - namedType.TupleElements.Select(f => f.Type), - t => t.BuildDisplayName(cx, trapFile)); + namedType.GetTupleElementsMaybeNull(), + (i, f) => + { + if (f is null) + trapFile.Write($"null({i})"); + else + f.Type.BuildDisplayName(cx, trapFile); + }); trapFile.Write(")"); return; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 028a0259a55..be4fe339975 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -413,15 +413,21 @@ namespace Semmle.Extraction.CSharp internal static void directive_nullables(this TextWriter trapFile, NullableDirective directive, int setting, int target) => trapFile.WriteTuple("directive_nullables", directive, setting, target); - internal static void directive_lines(this TextWriter trapFile, LineDirective directive, int kind) => - trapFile.WriteTuple("directive_lines", directive, kind); + internal static void directive_lines(this TextWriter trapFile, LineOrSpanDirective directive, LineDirectiveKind kind) where T : LineOrSpanDirectiveTriviaSyntax => + trapFile.WriteTuple("directive_lines", directive, (int)kind); internal static void directive_line_value(this TextWriter trapFile, LineDirective directive, int line) => trapFile.WriteTuple("directive_line_value", directive, line); - internal static void directive_line_file(this TextWriter trapFile, LineDirective directive, Extraction.Entities.File file) => + internal static void directive_line_file(this TextWriter trapFile, LineOrSpanDirective directive, Extraction.Entities.File file) where T : LineOrSpanDirectiveTriviaSyntax => trapFile.WriteTuple("directive_line_file", directive, file); + internal static void directive_line_offset(this TextWriter trapFile, LineSpanDirective directive, int offset) => + trapFile.WriteTuple("directive_line_offset", directive, offset); + + internal static void directive_line_span(this TextWriter trapFile, LineSpanDirective directive, int startLine, int startColumn, int endLine, int endColumn) => + trapFile.WriteTuple("directive_line_span", directive, startLine, startColumn, endLine, endColumn); + internal static void directive_regions(this TextWriter trapFile, RegionDirective directive, string name) => trapFile.WriteTuple("directive_regions", directive, name); @@ -451,7 +457,7 @@ namespace Semmle.Extraction.CSharp internal static void locations_mapped(this System.IO.TextWriter trapFile, NonGeneratedSourceLocation l1, Location l2) => trapFile.WriteTuple("locations_mapped", l1, l2); - internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, int mode) => + internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, ExtractorMode mode) => trapFile.WriteTuple("file_extraction_mode", file, mode); } } diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 99da916d294..2cc1ca440b0 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -400,7 +400,7 @@ namespace Semmle.Extraction private void ReportError(InternalError error) { - if (!Extractor.Standalone) + if (!Extractor.Mode.HasFlag(ExtractorMode.Standalone)) throw error; ExtractionError(error); diff --git a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs index a40c12d7eee..b16022181df 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs @@ -8,7 +8,7 @@ namespace Semmle.Extraction /// public abstract class Extractor { - public abstract bool Standalone { get; } + public abstract ExtractorMode Mode { get; } /// /// Creates a new extractor instance for one compilation unit. diff --git a/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs new file mode 100644 index 00000000000..52ef15f52d4 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs @@ -0,0 +1,16 @@ +using System; + +namespace Semmle.Extraction +{ + /// + /// The mode in which a file is extracted. + /// + [Flags] + public enum ExtractorMode + { + None = 0, + Standalone = 1, + Pdb = 2, + QlTest = 4, + } +} diff --git a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs index 7d4df42ef29..4244e34795a 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs @@ -4,15 +4,20 @@ namespace Semmle.Extraction { public class StandaloneExtractor : Extractor { - public override bool Standalone => true; + public override ExtractorMode Mode { get; } /// /// Creates a new extractor instance for one compilation unit. /// /// The object used for logging. /// The object used for path transformations. - public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer) + public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer) { + Mode = ExtractorMode.Standalone; + if (options.QlTest) + { + Mode |= ExtractorMode.QlTest; + } } } } diff --git a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs index eb92f35ad6e..d43dd891bbe 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs @@ -4,8 +4,7 @@ namespace Semmle.Extraction { public class TracingExtractor : Extractor { - public override bool Standalone => false; - + public override ExtractorMode Mode { get; } public string OutputPath { get; } /// @@ -14,9 +13,14 @@ namespace Semmle.Extraction /// The name of the output DLL/EXE, or null if not specified (standalone extraction). /// The object used for logging. /// The object used for path transformations. - public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer) + public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer) { OutputPath = outputPath; + Mode = ExtractorMode.None; + if (options.QlTest) + { + Mode |= ExtractorMode.QlTest; + } } } } diff --git a/csharp/extractor/Semmle.Extraction/Options.cs b/csharp/extractor/Semmle.Extraction/Options.cs index fffe3c88b4b..3ec033c144d 100644 --- a/csharp/extractor/Semmle.Extraction/Options.cs +++ b/csharp/extractor/Semmle.Extraction/Options.cs @@ -44,6 +44,11 @@ namespace Semmle.Extraction /// public bool Fast { get; private set; } = false; + /// + /// Whether extraction is done using `codeql test run`. + /// + public bool QlTest { get; private set; } = false; + /// /// The compression algorithm used for trap files. /// @@ -70,6 +75,10 @@ namespace Semmle.Extraction { switch (flag) { + case "silent": + if (value) + Verbosity = Verbosity.Off; + return true; case "verbose": Verbosity = value ? Verbosity.Debug : Verbosity.Error; return true; @@ -90,6 +99,9 @@ namespace Semmle.Extraction CIL = !value; Fast = value; return true; + case "qltest": + QlTest = value; + return true; case "brotli": TrapCompression = value ? TrapWriter.CompressionMode.Brotli : TrapWriter.CompressionMode.Gzip; return true; diff --git a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs index e1343019335..5c65e41f0ab 100644 --- a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs +++ b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs @@ -232,19 +232,33 @@ namespace Semmle.Extraction /// The list of items. /// The action on each item. /// The original trap builder (fluent interface). - public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action) + public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action) where T1 : TextWriter { var first = true; + var i = 0; foreach (var item in items) { if (first) first = false; else trapFile.Write(separator); - action(item); + action(i++, item); } return trapFile; } + + /// + /// Builds a trap builder using a separator and an action for each item in the list. + /// + /// The type of the items. + /// The trap builder to append to. + /// The separator string (e.g. ",") + /// The list of items. + /// The action on each item. + /// The original trap builder (fluent interface). + public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action) + where T1 : TextWriter => + trapFile.BuildList(separator, items, (_, item) => action(item)); } } diff --git a/csharp/ql/lib/Linq/Helpers.qll b/csharp/ql/lib/Linq/Helpers.qll index dc347c2f0d3..a3c5667c8bb 100644 --- a/csharp/ql/lib/Linq/Helpers.qll +++ b/csharp/ql/lib/Linq/Helpers.qll @@ -46,7 +46,7 @@ predicate missedAllOpportunity(ForeachStmt fes) { bl = a.getRValue() and bl.toString() = "false" ) and - exists(BreakStmt bs | bs = is.getThen().getAChild*()) + is.getThen().getAChild*() instanceof BreakStmt ) } diff --git a/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md new file mode 100644 index 00000000000..dad981966ba --- /dev/null +++ b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The query `cs/local-shadows-member` no longer highlights parameters of `record` types. \ No newline at end of file diff --git a/csharp/ql/lib/semmle/code/cil/Types.qll b/csharp/ql/lib/semmle/code/cil/Types.qll index 1dfaa0191a1..6bb980d6a87 100644 --- a/csharp/ql/lib/semmle/code/cil/Types.qll +++ b/csharp/ql/lib/semmle/code/cil/Types.qll @@ -61,7 +61,7 @@ class Class extends ValueOrRefType { } /** A `record`. */ -class Record extends Class { +deprecated class Record extends Class { Record() { this.isRecord() } } diff --git a/csharp/ql/lib/semmle/code/csharp/File.qll b/csharp/ql/lib/semmle/code/csharp/File.qll index f0ee0d6ca7f..5fc0d29e0b6 100644 --- a/csharp/ql/lib/semmle/code/csharp/File.qll +++ b/csharp/ql/lib/semmle/code/csharp/File.qll @@ -218,7 +218,12 @@ class File extends Container, @file { * A source file can come from a PDB and from regular extraction * in the same snapshot. */ - predicate isPdbSourceFile() { file_extraction_mode(this, 2) } + predicate isPdbSourceFile() { + exists(int i | + file_extraction_mode(this, i) and + i.bitAnd(2) = 2 + ) + } } /** @@ -228,5 +233,10 @@ class SourceFile extends File { SourceFile() { this.fromSource() } /** Holds if the file was extracted without building the source code. */ - predicate extractedStandalone() { file_extraction_mode(this, 1) } + predicate extractedStandalone() { + exists(int i | + file_extraction_mode(this, i) and + i.bitAnd(1) = 1 + ) + } } diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll index 3342dd5c59c..604e43d18b8 100644 --- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll +++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll @@ -208,21 +208,42 @@ class HiddenLineDirective extends LineDirective { override string getAPrimaryQlClass() { result = "HiddenLineDirective" } } +private class NumericOrSpanLineDirective extends LineDirective { + NumericOrSpanLineDirective() { directive_lines(this, [2, 3]) } + + /** Gets the referenced file of this directive. */ + File getReferencedFile() { directive_line_file(this, result) } +} + /** - * A numeric `#line` directive, such as `#line 200 file` + * A numeric `#line` directive, such as `#line 200 file`. */ -class NumericLineDirective extends LineDirective { +class NumericLineDirective extends NumericOrSpanLineDirective { NumericLineDirective() { directive_lines(this, 2) } /** Gets the line number of this directive. */ int getLine() { directive_line_value(this, result) } - /** Gets the referenced file of this directive. */ - File getReferencedFile() { directive_line_file(this, result) } - override string getAPrimaryQlClass() { result = "NumericLineDirective" } } +/** + * A line span `#line` directive, such as `#line (1, 1) - (3, 10) 5 file`. + */ +class SpanLineDirective extends NumericOrSpanLineDirective { + SpanLineDirective() { directive_lines(this, 3) } + + /** Gets the offset of this directive. */ + int getOffset() { directive_line_offset(this, result) } + + /** Holds if the specified start and end positions match this SpanLineDirective. */ + predicate span(int startLine, int startColumn, int endLine, int endColumn) { + directive_line_span(this, startLine, startColumn, endLine, endColumn) + } + + override string getAPrimaryQlClass() { result = "SpanLineDirective" } +} + /** * A `#region` directive. */ diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll index 5aeaeb904d5..c7f1515990b 100644 --- a/csharp/ql/lib/semmle/code/csharp/Type.qll +++ b/csharp/ql/lib/semmle/code/csharp/Type.qll @@ -372,6 +372,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ nested_types(this, _, result) } + override predicate isRecord() { this.hasModifier("record") } + override string toString() { result = Type.super.toString() } } @@ -449,6 +451,14 @@ class SimpleType extends ValueType, @simple_type { override SystemNamespace getDeclaringNamespace() { any() } } +/** + * A `record` like type. + * This can be either a `class` or a `struct`. + */ +class RecordType extends ValueOrRefType { + RecordType() { this.isRecord() } +} + /** * The Boolean type, `bool`. */ @@ -711,6 +721,18 @@ class Struct extends ValueType, @struct_type { override string getAPrimaryQlClass() { result = "Struct" } } +/** + * A `record struct`, for example + * ```csharp + * record struct RS { + * ... + * } + * ``` + */ +class RecordStruct extends RecordType, Struct { + override string getAPrimaryQlClass() { result = "RecordStruct" } +} + /** * A reference type. * @@ -765,6 +787,16 @@ class Class extends RefType, @class_type { override string getAPrimaryQlClass() { result = "Class" } } +/** + * DEPRECATED: Use `RecordClass` instead. + */ +deprecated class Record extends Class { + Record() { this.isRecord() } + + /** Gets the clone method of this record. */ + RecordCloneMethod getCloneMethod() { result = this.getAMember() } +} + /** * A `record`, for example * @@ -774,13 +806,11 @@ class Class extends RefType, @class_type { * } * ``` */ -class Record extends Class { - Record() { this.isRecord() } - +class RecordClass extends RecordType, Class { /** Gets the clone method of this record. */ RecordCloneMethod getCloneMethod() { result = this.getAMember() } - override string getAPrimaryQlClass() { result = "Record" } + override string getAPrimaryQlClass() { result = "RecordClass" } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/XML.qll b/csharp/ql/lib/semmle/code/csharp/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/csharp/ql/lib/semmle/code/csharp/XML.qll +++ b/csharp/ql/lib/semmle/code/csharp/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll index 94b3d8d7d4d..3ae9c7667d0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll @@ -111,7 +111,7 @@ module SummaryComponentStack { class SummarizedCallable = Impl::Public::SummarizedCallable; private predicate recordConstructorFlow(Constructor c, int i, Property p) { - c = any(Record r).getAMember() and + c = any(RecordType r).getAMember() and exists(string name | c.getParameter(i).getName() = name and c.getDeclaringType().getAMember(name) = p @@ -153,15 +153,11 @@ private class SummarizedCallableDefaultClearsContent extends Impl::Public::Summa class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack; private class RecordConstructorFlowRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private SummaryComponent head; - - RecordConstructorFlowRequiredSummaryComponentStack() { + override predicate required(SummaryComponent head, SummaryComponentStack tail) { exists(Property p | recordConstructorFlow(_, _, p) and head = SummaryComponent::property(p) and - this = SummaryComponentStack::return() + tail = SummaryComponentStack::return() ) } - - override predicate required(SummaryComponent c) { c = head } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index cdf3923c195..5bdf9b3c0de 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1481,6 +1481,8 @@ class FieldOrProperty extends Assignable, Modifiable { p.isAutoImplemented() or p.matchesHandle(any(CIL::TrivialProperty tp)) + or + p.getDeclaringType() instanceof AnonymousClass ) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 60af91e291b..1ded4e7bed1 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -175,11 +175,11 @@ module Public { * A class that exists for QL technical reasons only (the IPA type used * to represent component stacks needs to be bounded). */ - abstract class RequiredSummaryComponentStack extends SummaryComponentStack { + class RequiredSummaryComponentStack extends Unit { /** * Holds if the stack obtained by pushing `head` onto `tail` is required. */ - abstract predicate required(SummaryComponent c); + abstract predicate required(SummaryComponent head, SummaryComponentStack tail); } /** A callable with a flow summary. */ @@ -240,9 +240,9 @@ module Private { newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { - tail.(RequiredSummaryComponentStack).required(head) + any(RequiredSummaryComponentStack x).required(head, tail) or - tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and head = thisParam() or derivedFluentFlowPush(_, _, _, head, tail, _) @@ -890,9 +890,9 @@ module Private { } private class MkStack extends RequiredSummaryComponentStack { - MkStack() { interpretSpec(_, _, _, this) } - - override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) } + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + interpretSpec(_, _, head, tail) + } } private class SummarizedCallableExternal extends SummarizedCallable { diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 1fbba72f864..4d994ed2afb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -292,7 +292,7 @@ private module Internal { pragma[nomagic] predicate hasSubsumedQualifierTypeOverridden(Gvn::GvnType t, OverridableCallable c) { this.hasSubsumedQualifierType(t) and - hasCallable(t, c, any(OverridableCallable oc | oc = this.getAStaticTargetExt())) + hasCallable(t, c, this.getAStaticTargetExt()) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 1007d2cefe6..1a869f2458c 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -1175,7 +1175,9 @@ class WithExpr extends Expr, @with_expr { Expr getExpr() { result = this.getChild(0) } /** Gets the clone method of the `record` that is targetted by this `with` expression. */ - RecordCloneMethod getCloneMethod() { result = this.getExpr().getType().(Record).getCloneMethod() } + RecordCloneMethod getCloneMethod() { + result = this.getExpr().getType().(RecordClass).getCloneMethod() + } override string toString() { result = "... with { ... }" } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll index b586c4cffb1..5def0963292 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll @@ -91,14 +91,10 @@ module EntityFramework { abstract class EFSummarizedCallable extends SummarizedCallable { } private class DbSetAddOrUpdateRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private SummaryComponent head; - - DbSetAddOrUpdateRequiredSummaryComponentStack() { - this = SummaryComponentStack::argument([-1, 0]) and - head = SummaryComponent::element() + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + head = SummaryComponent::element() and + tail = SummaryComponentStack::argument([-1, 0]) } - - override predicate required(SummaryComponent c) { c = head } } private class DbSetAddOrUpdate extends EFSummarizedCallable { @@ -462,14 +458,12 @@ module EntityFramework { } private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack { - private Content head; - - DbContextSaveChangesRequiredSummaryComponentStack() { - any(DbContextClass c).requiresComponentStackIn(head, _, this, _) - or - any(DbContextClass c).requiresComponentStackOut(head, _, this, _) + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + exists(Content c | head = SummaryComponent::content(c) | + any(DbContextClass cls).requiresComponentStackIn(c, _, tail, _) + or + any(DbContextClass cls).requiresComponentStackOut(c, _, tail, _) + ) } - - override predicate required(SummaryComponent c) { c = SummaryComponent::content(head) } } } diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme index 193c35b0e37..ff083666c7f 100644 --- a/csharp/ql/lib/semmlecode.csharp.dbscheme +++ b/csharp/ql/lib/semmlecode.csharp.dbscheme @@ -385,7 +385,7 @@ directive_endregions( directive_lines( unique int id: @directive_line, - int kind: int ref); /* 0: default, 1: hidden, 2: numeric */ + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ directive_line_value( unique int id: @directive_line ref, @@ -393,8 +393,18 @@ directive_line_value( directive_line_file( unique int id: @directive_line ref, - int file: @file ref -) + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); directive_nullables( unique int id: @directive_nullable, diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats index 46d7b963528..f458da72beb 100644 --- a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats @@ -42,11 +42,11 @@ @folder - 484046 + 484045 @namespace - 367576 + 367575 @namespace_declaration @@ -174,19 +174,19 @@ @struct_type - 1223176 + 1223173 @class_type - 3789357 + 3789350 @interface_type - 2384809 + 2384805 @delegate_type - 2249826 + 2249822 @null_type @@ -194,7 +194,7 @@ @type_parameter - 831792 + 831790 @pointer_type @@ -242,23 +242,23 @@ @typeref - 3537567 - - - @location_default - 43578550 + 3537560 @attribute - 10551347 + 10551328 @type_mention - 4147997 + 4147990 + + + @location_default + 43578472 @oblivious - 15642 + 15641 @not_annotated @@ -270,7 +270,7 @@ @type_parameter_constraints - 1730282 + 1730279 @modifier @@ -278,7 +278,7 @@ @property - 4879894 + 4879885 @indexer @@ -286,11 +286,11 @@ @getter - 4950272 + 4950263 @setter - 864801 + 864799 @event @@ -306,15 +306,15 @@ @operator - 807643 + 807641 @method - 15027131 + 15027104 @constructor - 4401500 + 4401492 @destructor @@ -326,15 +326,15 @@ @addressable_field - 8156775 + 8156760 @constant - 2845825 + 2845820 @addressable_local_variable - 353480 + 353479 @local_constant @@ -346,15 +346,15 @@ @parameter - 27466281 + 27466231 @block_stmt - 470421 + 470420 @expr_stmt - 493565 + 493564 @if_stmt @@ -382,7 +382,7 @@ @break_stmt - 42189 + 42188 @continue_stmt @@ -390,7 +390,7 @@ @goto_stmt - 3587 + 3586 @goto_case_stmt @@ -466,7 +466,7 @@ @local_function_stmt - 3317 + 3316 @using_decl_stmt @@ -474,7 +474,7 @@ @bool_literal_expr - 585969 + 585968 @char_literal_expr @@ -482,7 +482,7 @@ @int_literal_expr - 3350910 + 3350904 @long_literal_expr @@ -506,11 +506,11 @@ @string_literal_expr - 1548385 + 1548382 @null_literal_expr - 155827 + 155826 @this_access_expr @@ -522,11 +522,11 @@ @local_variable_access_expr - 1030138 + 1030136 @parameter_access_expr - 969868 + 969866 @field_access_expr @@ -534,7 +534,7 @@ @property_access_expr - 1360056 + 1360054 @method_access_expr @@ -554,15 +554,15 @@ @type_access_expr - 919476 + 919474 @typeof_expr - 439082 + 439081 @method_invocation_expr - 832881 + 832863 @delegate_invocation_expr @@ -570,15 +570,15 @@ @operator_invocation_expr - 778750 + 778748 @cast_expr - 540190 + 540196 @object_creation_expr - 438905 + 438904 @explicit_delegate_creation_expr @@ -590,11 +590,11 @@ @array_creation_expr - 349824 + 349823 @default_expr - 790760 + 790758 @minus_expr @@ -710,7 +710,7 @@ @simple_assign_expr - 1592072 + 1592070 @assign_add_expr @@ -730,7 +730,7 @@ @object_init_expr - 383017 + 383016 @collection_init_expr @@ -762,11 +762,11 @@ @local_var_decl_expr - 354491 + 354490 @lambda_expr - 733508 + 733506 @anonymous_method_expr @@ -802,7 +802,7 @@ @decimal_literal_expr - 131181 + 131180 @plus_expr @@ -958,11 +958,11 @@ @xmlelement - 1042734675 + 1042732803 @xmlattribute - 782957811 + 782956405 @xmlnamespace @@ -974,7 +974,7 @@ @xmlcharacters - 808544061 + 808542609 @singlelinecomment @@ -982,7 +982,7 @@ @xmldoccomment - 1212394 + 1212392 @multilinecomment @@ -990,7 +990,7 @@ @commentblock - 412296 + 412295 @asp_close_tag @@ -1030,11 +1030,11 @@ @cil_valueorreftype - 7660331 + 7660317 @cil_typeparameter - 1302994 + 1302992 @cil_array_type @@ -1050,11 +1050,11 @@ @cil_method - 28926216 + 28926164 @cil_ceq - 683258 + 683257 @cil_cgt @@ -1062,11 +1062,11 @@ @cil_cgt_un - 260989 + 260988 @cil_clt - 55669 + 55668 @cil_clt_un @@ -1074,7 +1074,7 @@ @cil_ldftn - 2118027 + 2118023 @cil_ldvirtftn @@ -1110,11 +1110,11 @@ @cil_initobj - 698444 + 698443 @cil_constrained - 557146 + 557145 @cil_cpblk @@ -1138,7 +1138,7 @@ @cil_stsfld - 1909496 + 1909493 @cil_stobj @@ -1146,19 +1146,19 @@ @cil_box - 1043089 + 1043087 @cil_newarr - 1178162 + 1178159 @cil_ldlen - 418971 + 418970 @cil_ldelema - 524864 + 524863 @cil_ldelem_i1 @@ -1202,7 +1202,7 @@ @cil_ldelem_ref - 253309 + 253308 @cil_stelem_i @@ -1230,7 +1230,7 @@ @cil_stelem_ref - 3101391 + 3101385 @cil_ldelem @@ -1258,7 +1258,7 @@ @cil_ldtoken - 749623 + 749621 @cil_conv_u2 @@ -1266,7 +1266,7 @@ @cil_conv_u1 - 175034 + 175033 @cil_conv_i @@ -1290,15 +1290,15 @@ @cil_endfinally - 1445725 + 1445722 @cil_leave - 508918 + 508917 @cil_leave_s - 2302564 + 2302560 @cil_stind_i @@ -1310,131 +1310,131 @@ @cil_nop - 1547248 + 1547241 @cil_ldarg_0 - 39364252 + 39364181 @cil_ldarg_1 - 15405533 + 15405506 @cil_ldarg_2 - 5488999 + 5488989 @cil_ldarg_3 - 2376435 + 2376431 @cil_ldloc_0 - 12928933 + 12928909 @cil_ldloc_1 - 6975728 + 6975715 @cil_ldloc_2 - 4951075 + 4951066 @cil_ldloc_3 - 3108312 + 3108306 @cil_stloc_0 - 6417366 + 6417355 @cil_stloc_1 - 3676175 + 3676168 @cil_stloc_2 - 2658099 + 2658095 @cil_stloc_3 - 1822152 + 1822149 @cil_ldarg_s - 2508752 + 2508747 @cil_ldarga_s - 917085 + 917084 @cil_starg_s - 198638 + 198637 @cil_ldloc_s - 10621053 + 10621034 @cil_ldloca_s - 7189487 + 7189474 @cil_stloc_s - 6640346 + 6640335 @cil_ldnull - 5392406 + 5392397 @cil_ldc_i4_m1 - 640280 + 640279 @cil_ldc_i4_0 - 7980548 + 7980533 @cil_ldc_i4_1 - 6322972 + 6322961 @cil_ldc_i4_2 - 1431536 + 1431534 @cil_ldc_i4_3 - 788673 + 788672 @cil_ldc_i4_4 - 724283 + 724282 @cil_ldc_i4_5 - 424937 + 424936 @cil_ldc_i4_6 - 245434 + 245433 @cil_ldc_i4_7 - 218055 + 218054 @cil_ldc_i4_8 - 326616 + 326615 @cil_ldc_i4_s - 3951635 + 3951628 @cil_ldc_i4 - 2083966 + 2083962 @cil_ldc_i8 @@ -1442,7 +1442,7 @@ @cil_ldc_r4 - 22823 + 22822 @cil_ldc_r8 @@ -1450,15 +1450,15 @@ @cil_dup - 6812192 + 6812179 @cil_pop - 2850598 + 2850593 @cil_call - 35891791 + 35891726 @cil_calli @@ -1466,23 +1466,23 @@ @cil_ret - 23260143 + 23260101 @cil_br_s - 4244082 + 4244074 @cil_brfalse_s - 7354021 + 7354008 @cil_brtrue_s - 6868468 + 6868456 @cil_beq_s - 1166967 + 1166965 @cil_bge_s @@ -1494,15 +1494,15 @@ @cil_ble_s - 251335 + 251334 @cil_blt_s - 426846 + 426845 @cil_bne_un_s - 1697190 + 1697187 @cil_bge_un_s @@ -1522,19 +1522,19 @@ @cil_br - 1052158 + 1052156 @cil_brfalse - 700831 + 700830 @cil_brtrue - 590512 + 590511 @cil_beq - 308566 + 308565 @cil_bge @@ -1542,7 +1542,7 @@ @cil_bgt - 26164 + 26163 @cil_ble @@ -1626,7 +1626,7 @@ @cil_stind_i4 - 324338 + 324337 @cil_stind_i8 @@ -1642,15 +1642,15 @@ @cil_add - 1977553 + 1977549 @cil_sub - 739882 + 739880 @cil_mul - 313317 + 313316 @cil_div @@ -1670,11 +1670,11 @@ @cil_and - 371763 + 371762 @cil_or - 165879 + 165878 @cil_xor @@ -1710,7 +1710,7 @@ @cil_conv_i4 - 392308 + 392307 @cil_conv_i8 @@ -1734,7 +1734,7 @@ @cil_callvirt - 30280801 + 30280746 @cil_cpobj @@ -1746,19 +1746,19 @@ @cil_ldstr - 8268547 + 8268532 @cil_newobj - 9351013 + 9350996 @cil_castclass - 1325296 + 1325294 @cil_isinst - 2016430 + 2016426 @cil_conv_r_un @@ -1770,23 +1770,23 @@ @cil_throw - 5164351 + 5164341 @cil_ldfld - 16903695 + 16903665 @cil_ldflda - 1433641 + 1433638 @cil_stfld - 8348623 + 8348608 @cil_ldsfld - 7724179 + 7724165 @cil_ldsflda @@ -1926,19 +1926,19 @@ @cil_method_implementation - 19889366 + 19889330 @cil_field - 11684992 + 11684971 @cil_parameter - 55186717 + 55186618 @cil_property - 4409961 + 4409953 @cil_event @@ -1946,7 +1946,7 @@ @cil_local_variable - 16916582 + 16916551 @cil_catch_handler @@ -1958,15 +1958,15 @@ @cil_finally_handler - 1221334 + 1221332 @cil_fault_handler - 224390 + 224389 @cil_attribute - 4315762 + 4315754 @@ -2677,7 +2677,7 @@ compilation_referencing_files - 523639 + 523638 id @@ -2921,57 +2921,57 @@ 5 6 - 1143 + 774 6 7 - 497 + 866 7 16 - 304 + 322 16 20 - 451 + 433 20 - 24 - 424 + 25 + 442 - 24 - 30 - 451 + 25 + 29 + 433 - 30 + 29 46 - 460 + 424 46 - 55 - 387 - - - 55 - 58 - 507 - - - 58 - 63 + 56 424 + + 56 + 59 + 451 + + + 59 + 63 + 405 + 63 - 65 - 64 + 66 + 138 @@ -3048,62 +3048,67 @@ 2 5 - 460 + 451 5 6 - 294 + 350 6 7 - 755 + 691 7 10 - 488 + 497 10 15 - 479 + 516 15 20 - 516 + 507 20 - 26 - 433 + 25 + 451 - 26 - 31 + 25 + 35 460 - 31 - 57 - 553 + 35 + 58 + 387 - 57 + 58 59 - 414 + 276 59 - 61 + 60 + 350 + + + 60 + 63 460 - 61 - 68 - 175 + 63 + 67 + 92 @@ -3129,7 +3134,7 @@ seconds - 7817 + 8333 @@ -3172,15 +3177,10 @@ 12 - - 6 - 7 - 9 - 7 8 - 1613 + 1622 @@ -3226,8 +3226,8 @@ 12 - 848 - 849 + 904 + 905 9 @@ -3273,24 +3273,24 @@ 12 - - 116 - 117 - 9 - - - 118 - 119 - 9 - 125 126 9 - 135 - 136 + 130 + 131 + 9 + + + 140 + 141 + 9 + + + 144 + 145 9 @@ -3312,22 +3312,22 @@ 1 2 - 6102 + 6664 2 3 - 700 + 912 3 - 4 - 488 + 6 + 728 - 4 + 6 8 - 525 + 27 @@ -3343,7 +3343,7 @@ 1 2 - 7817 + 8333 @@ -3359,17 +3359,17 @@ 1 2 - 6416 + 6996 2 3 - 1198 + 1179 3 - 4 - 202 + 5 + 156 @@ -5493,7 +5493,7 @@ cpu_seconds - 1364 + 1438 elapsed_seconds @@ -5543,17 +5543,17 @@ 1 2 - 1143 + 1272 2 3 - 184 + 147 3 4 - 36 + 18 @@ -5569,17 +5569,17 @@ 1 2 - 1143 + 1272 2 3 - 184 + 147 3 4 - 36 + 18 @@ -6765,11 +6765,11 @@ locations_default - 43578550 + 43578472 id - 43578550 + 43578472 file @@ -6777,7 +6777,7 @@ beginLine - 2347256 + 2347252 beginColumn @@ -6785,7 +6785,7 @@ endLine - 2511837 + 2511832 endColumn @@ -6803,7 +6803,7 @@ 1 2 - 43578550 + 43578472 @@ -6819,7 +6819,7 @@ 1 2 - 43578550 + 43578472 @@ -6835,7 +6835,7 @@ 1 2 - 43578550 + 43578472 @@ -6851,7 +6851,7 @@ 1 2 - 43578550 + 43578472 @@ -6867,7 +6867,7 @@ 1 2 - 43578550 + 43578472 @@ -7283,7 +7283,7 @@ 2 3 - 443707 + 443706 3 @@ -7298,12 +7298,12 @@ 5 6 - 177016 + 177015 6 7 - 184061 + 184060 7 @@ -7328,12 +7328,12 @@ 24 92 - 176252 + 176251 92 759 - 128380 + 128379 @@ -7349,22 +7349,22 @@ 1 2 - 1044823 + 1044821 2 3 - 387177 + 387176 3 4 - 354923 + 354922 4 6 - 187923 + 187922 6 @@ -7395,7 +7395,7 @@ 1 2 - 333364 + 333363 2 @@ -7425,22 +7425,22 @@ 7 9 - 173833 + 173832 9 13 - 185037 + 185036 13 24 - 183000 + 182999 24 98 - 176252 + 176251 98 @@ -7461,12 +7461,12 @@ 1 2 - 1025258 + 1025256 2 3 - 731193 + 731192 3 @@ -7476,7 +7476,7 @@ 4 6 - 188984 + 188983 6 @@ -7502,7 +7502,7 @@ 2 3 - 443919 + 443918 3 @@ -7512,7 +7512,7 @@ 4 5 - 278574 + 278573 5 @@ -7527,17 +7527,17 @@ 7 8 - 134067 + 134066 8 10 - 178289 + 178288 10 14 - 184740 + 184739 14 @@ -7903,7 +7903,7 @@ 3 4 - 280187 + 280186 4 @@ -7959,7 +7959,7 @@ 1 2 - 1096387 + 1096385 2 @@ -7969,12 +7969,12 @@ 3 4 - 490560 + 490559 4 6 - 207700 + 207699 6 @@ -7984,7 +7984,7 @@ 12 61 - 189748 + 189747 61 @@ -8005,12 +8005,12 @@ 1 2 - 1365582 + 1365580 2 3 - 545987 + 545986 3 @@ -8041,17 +8041,17 @@ 1 2 - 483133 + 483132 2 3 - 397193 + 397192 3 4 - 212156 + 212155 4 @@ -8071,22 +8071,22 @@ 7 9 - 200952 + 200951 9 13 - 204814 + 204813 13 24 - 191106 + 191105 24 126 - 188517 + 188516 128 @@ -8107,7 +8107,7 @@ 1 2 - 440948 + 440947 2 @@ -8127,7 +8127,7 @@ 5 6 - 219583 + 219582 6 @@ -8244,7 +8244,7 @@ 1 2 - 14769 + 14768 2 @@ -8264,7 +8264,7 @@ 6 11 - 4923 + 4922 11 @@ -8555,11 +8555,11 @@ numlines - 1043663828 + 1043661954 element_id - 1043663828 + 1043661954 num_lines @@ -8567,7 +8567,7 @@ num_code - 243293 + 243292 num_comment @@ -8585,7 +8585,7 @@ 1 2 - 1043663828 + 1043661954 @@ -8601,7 +8601,7 @@ 1 2 - 1043663828 + 1043661954 @@ -8617,7 +8617,7 @@ 1 2 - 1043663828 + 1043661954 @@ -9492,15 +9492,15 @@ folders - 484046 + 484045 id - 484046 + 484045 name - 484046 + 484045 @@ -9514,7 +9514,7 @@ 1 2 - 484046 + 484045 @@ -9530,7 +9530,7 @@ 1 2 - 484046 + 484045 @@ -9540,15 +9540,15 @@ containerparent - 992135 + 992133 parent - 484046 + 484045 child - 992135 + 992133 @@ -9562,7 +9562,7 @@ 1 2 - 379754 + 379753 2 @@ -9593,7 +9593,7 @@ 1 2 - 992135 + 992133 @@ -9651,11 +9651,11 @@ namespaces - 367576 + 367575 id - 367576 + 367575 name @@ -9673,7 +9673,7 @@ 1 2 - 367576 + 367575 @@ -9870,15 +9870,15 @@ parent_namespace - 7241099 + 7241086 child_id - 7241099 + 7241086 namespace_id - 231289 + 231288 @@ -9892,7 +9892,7 @@ 1 2 - 7241099 + 7241086 @@ -9933,7 +9933,7 @@ 6 8 - 17703 + 17702 8 @@ -9953,7 +9953,7 @@ 44 84811 - 13082 + 13081 @@ -11615,6 +11615,300 @@ + + directive_line_offset + 0 + + + id + 0 + + + offset + 0 + + + + + id + offset + + + 12 + + + 1 + 2 + 14 + + + + + + + offset + id + + + 12 + + + + + + + + directive_line_span + 0 + + + id + 0 + + + startLine + 0 + + + startColumn + 0 + + + endLine + 0 + + + endColumn + 0 + + + + + id + startLine + + + 12 + + + 1 + 2 + 14 + + + + + + + id + startColumn + + + 12 + + + 1 + 2 + 14 + + + + + + + id + endLine + + + 12 + + + 1 + 2 + 14 + + + + + + + id + endColumn + + + 12 + + + 1 + 2 + 14 + + + + + + + startLine + id + + + 12 + + + + + + startLine + startColumn + + + 12 + + + + + + startLine + endLine + + + 12 + + + + + + startLine + endColumn + + + 12 + + + + + + startColumn + id + + + 12 + + + + + + startColumn + startLine + + + 12 + + + + + + startColumn + endLine + + + 12 + + + + + + startColumn + endColumn + + + 12 + + + + + + endLine + id + + + 12 + + + + + + endLine + startLine + + + 12 + + + + + + endLine + startColumn + + + 12 + + + + + + endLine + endColumn + + + 12 + + + + + + endColumn + id + + + 12 + + + + + + endColumn + startLine + + + 12 + + + + + + endColumn + startColumn + + + 12 + + + + + + endColumn + endLine + + + 12 + + + + + + directive_nullables 3382 @@ -12590,11 +12884,11 @@ types - 8463411 + 8463395 id - 8463411 + 8463395 kind @@ -12602,7 +12896,7 @@ name - 2569129 + 2569124 @@ -12616,7 +12910,7 @@ 1 2 - 8463411 + 8463395 @@ -12632,7 +12926,7 @@ 1 2 - 8463411 + 8463395 @@ -12735,7 +13029,7 @@ 1 2 - 2307988 + 2307983 2 @@ -12761,7 +13055,7 @@ 1 2 - 2548128 + 2548124 2 @@ -12776,15 +13070,15 @@ typerefs - 3537567 + 3537560 id - 3537567 + 3537560 name - 2476079 + 2476075 @@ -12798,7 +13092,7 @@ 1 2 - 3537567 + 3537560 @@ -12814,7 +13108,7 @@ 1 2 - 2298312 + 2298307 2 @@ -12829,15 +13123,15 @@ typeref_type - 3508083 + 3508077 id - 3508083 + 3508077 typeId - 3508083 + 3508077 @@ -12851,7 +13145,7 @@ 1 2 - 3508083 + 3508077 @@ -12867,7 +13161,7 @@ 1 2 - 3508083 + 3508077 @@ -13332,15 +13626,15 @@ delegate_return_type - 2249826 + 2249822 delegate_id - 2249826 + 2249822 return_type_id - 801531 + 801529 @@ -13354,7 +13648,7 @@ 1 2 - 2249826 + 2249822 @@ -13370,7 +13664,7 @@ 1 2 - 730409 + 730408 2 @@ -13458,11 +13752,11 @@ extend - 3548527 + 3548520 sub - 3547415 + 3547409 super @@ -13480,7 +13774,7 @@ 1 2 - 3546304 + 3546298 2 @@ -13552,15 +13846,15 @@ implement - 9498668 + 9498651 sub - 3317494 + 3317488 super - 2026887 + 2026883 @@ -13574,27 +13868,27 @@ 1 2 - 1125942 + 1125940 2 3 - 905522 + 905520 3 4 - 620560 + 620559 4 6 - 270036 + 270035 6 9 - 249057 + 249056 9 @@ -13615,12 +13909,12 @@ 1 2 - 973058 + 973056 2 3 - 598995 + 598994 3 @@ -13635,7 +13929,7 @@ 6 90747 - 122923 + 122922 @@ -13645,11 +13939,11 @@ type_location - 4526766 + 4526758 id - 4460402 + 4460394 loc @@ -13667,7 +13961,7 @@ 1 2 - 4438121 + 4438113 2 @@ -13796,7 +14090,7 @@ tuple_element - 149836 + 149835 tuple @@ -13808,7 +14102,7 @@ field - 149836 + 149835 @@ -14186,7 +14480,7 @@ 1 2 - 149836 + 149835 @@ -14202,7 +14496,7 @@ 1 2 - 149836 + 149835 @@ -14212,11 +14506,11 @@ attributes - 10551347 + 10551328 id - 10551347 + 10551328 type_id @@ -14224,7 +14518,7 @@ target - 9250913 + 9250896 @@ -14238,7 +14532,7 @@ 1 2 - 10551347 + 10551328 @@ -14254,7 +14548,7 @@ 1 2 - 10551347 + 10551328 @@ -14422,12 +14716,12 @@ 1 2 - 8608463 + 8608447 2 3520 - 642450 + 642449 @@ -14443,12 +14737,12 @@ 1 2 - 8733902 + 8733887 2 29 - 517010 + 517009 @@ -14458,11 +14752,11 @@ attribute_location - 10552714 + 10552695 id - 10551347 + 10551328 loc @@ -14480,7 +14774,7 @@ 1 2 - 10550263 + 10550244 2 @@ -14571,11 +14865,11 @@ type_mention - 4147997 + 4147990 id - 4147997 + 4147990 type_id @@ -14583,7 +14877,7 @@ parent - 1453787 + 1453785 @@ -14597,7 +14891,7 @@ 1 2 - 4147997 + 4147990 @@ -14613,7 +14907,7 @@ 1 2 - 4147997 + 4147990 @@ -14670,7 +14964,7 @@ 1 2 - 69690 + 69689 2 @@ -14711,12 +15005,12 @@ 1 2 - 1183982 + 1183979 2 3 - 142436 + 142435 3 @@ -14742,7 +15036,7 @@ 1 2 - 1271409 + 1271407 2 @@ -14762,15 +15056,15 @@ type_mention_location - 4147997 + 4147990 id - 4147997 + 4147990 loc - 3077665 + 3077659 @@ -14784,7 +15078,7 @@ 1 2 - 4147997 + 4147990 @@ -14800,12 +15094,12 @@ 1 2 - 2705130 + 2705125 2 3 - 359178 + 359177 3 @@ -14820,11 +15114,11 @@ type_annotation - 1491207 + 1491205 id - 1491207 + 1491205 annotation @@ -14842,7 +15136,7 @@ 1 2 - 1491207 + 1491205 @@ -15207,11 +15501,11 @@ type_nullability - 32568461 + 32568402 id - 32566139 + 32566081 nullability @@ -15229,7 +15523,7 @@ 1 2 - 32563905 + 32563846 2 @@ -15300,11 +15594,11 @@ expr_flowstate - 3848490 + 3848496 id - 3848490 + 3848496 state @@ -15322,7 +15616,7 @@ 1 2 - 3848490 + 3848496 @@ -15336,13 +15630,13 @@ 12 - 210405 - 210406 + 210406 + 210407 1 - 2276574 - 2276575 + 2276592 + 2276593 1 @@ -15353,11 +15647,11 @@ type_parameters - 830424 + 830422 id - 830424 + 830422 index @@ -15365,7 +15659,7 @@ generic_id - 796402 + 796400 variance @@ -15383,7 +15677,7 @@ 1 2 - 830424 + 830422 @@ -15399,7 +15693,7 @@ 1 2 - 830424 + 830422 @@ -15415,7 +15709,7 @@ 1 2 - 830424 + 830422 @@ -15639,7 +15933,7 @@ 1 2 - 789862 + 789861 2 @@ -15660,7 +15954,7 @@ 1 2 - 789862 + 789861 2 @@ -15681,7 +15975,7 @@ 1 2 - 796038 + 796037 2 @@ -15774,11 +16068,11 @@ type_arguments - 32946682 + 32946623 id - 851709 + 851708 index @@ -15786,7 +16080,7 @@ constructed_id - 3572654 + 3572648 @@ -15805,7 +16099,7 @@ 2 3 - 720386 + 720385 3 @@ -15831,7 +16125,7 @@ 2 3 - 721262 + 721261 3 @@ -16044,7 +16338,7 @@ 2 3 - 2211295 + 2211291 3 @@ -16054,17 +16348,17 @@ 20 25 - 281239 + 281238 25 29 - 321416 + 321415 29 32 - 283718 + 283717 32 @@ -16090,27 +16384,27 @@ 2 3 - 2211338 + 2211334 3 20 - 305986 + 305985 20 25 - 281239 + 281238 25 29 - 321416 + 321415 29 32 - 283718 + 283717 32 @@ -16125,11 +16419,11 @@ constructed_generic - 3862925 + 3862918 constructed - 3862925 + 3862918 generic @@ -16147,7 +16441,7 @@ 1 2 - 3862925 + 3862918 @@ -16213,15 +16507,15 @@ type_parameter_constraints - 1730282 + 1730279 id - 1730282 + 1730279 param_id - 831792 + 831790 @@ -16235,7 +16529,7 @@ 1 2 - 1730282 + 1730279 @@ -16256,7 +16550,7 @@ 2 3 - 777766 + 777765 3 @@ -16384,7 +16678,7 @@ id - 254828 + 254827 base_id @@ -16402,7 +16696,7 @@ 1 2 - 250207 + 250206 2 @@ -16463,11 +16757,11 @@ specific_type_parameter_nullability - 48893 + 48843 id - 48656 + 48606 base_id @@ -16489,7 +16783,7 @@ 1 2 - 48418 + 48369 2 @@ -16510,7 +16804,7 @@ 1 2 - 48656 + 48606 @@ -16686,8 +16980,8 @@ 1 - 35929 - 35930 + 35892 + 35893 1 @@ -16935,11 +17229,11 @@ has_modifiers - 74006635 + 74006502 id - 48974345 + 48974257 mod_id @@ -16957,17 +17251,17 @@ 1 2 - 25150157 + 25150112 2 3 - 22619211 + 22619170 3 5 - 1204976 + 1204974 @@ -17058,11 +17352,11 @@ compiler_generated - 786251 + 786249 id - 786251 + 786249 @@ -17157,19 +17451,19 @@ nested_types - 1588195 + 1588192 id - 1588195 + 1588192 declaring_type_id - 637373 + 637372 unbound_id - 1331870 + 1331867 @@ -17183,7 +17477,7 @@ 1 2 - 1588195 + 1588192 @@ -17199,7 +17493,7 @@ 1 2 - 1588195 + 1588192 @@ -17215,7 +17509,7 @@ 1 2 - 373000 + 372999 2 @@ -17235,7 +17529,7 @@ 6 22 - 47989 + 47988 22 @@ -17256,7 +17550,7 @@ 1 2 - 374540 + 374539 2 @@ -17297,7 +17591,7 @@ 1 2 - 1283295 + 1283293 2 @@ -17318,7 +17612,7 @@ 1 2 - 1291083 + 1291081 2 @@ -17333,27 +17627,27 @@ properties - 4879894 + 4879885 id - 4879894 + 4879885 name - 1131843 + 1131841 declaring_type_id - 1362395 + 1362392 type_id - 541612 + 541611 unbound_id - 4365920 + 4365913 @@ -17367,7 +17661,7 @@ 1 2 - 4879894 + 4879885 @@ -17383,7 +17677,7 @@ 1 2 - 4879894 + 4879885 @@ -17399,7 +17693,7 @@ 1 2 - 4879894 + 4879885 @@ -17415,7 +17709,7 @@ 1 2 - 4879894 + 4879885 @@ -17431,7 +17725,7 @@ 1 2 - 714282 + 714280 2 @@ -17467,7 +17761,7 @@ 1 2 - 714282 + 714280 2 @@ -17503,7 +17797,7 @@ 1 2 - 989546 + 989545 2 @@ -17529,12 +17823,12 @@ 1 2 - 720508 + 720507 2 3 - 186641 + 186640 3 @@ -17565,12 +17859,12 @@ 1 2 - 484967 + 484966 2 3 - 319782 + 319781 3 @@ -17585,7 +17879,7 @@ 5 7 - 114614 + 114613 7 @@ -17611,12 +17905,12 @@ 1 2 - 560096 + 560095 2 3 - 245846 + 245845 3 @@ -17657,7 +17951,7 @@ 1 2 - 562005 + 562004 2 @@ -17667,7 +17961,7 @@ 3 4 - 167788 + 167787 4 @@ -17698,12 +17992,12 @@ 1 2 - 484967 + 484966 2 3 - 319782 + 319781 3 @@ -17718,7 +18012,7 @@ 5 7 - 114614 + 114613 7 @@ -17790,7 +18084,7 @@ 2 3 - 60572 + 60571 3 @@ -17816,7 +18110,7 @@ 1 2 - 309846 + 309845 2 @@ -17857,12 +18151,12 @@ 1 2 - 297480 + 297479 2 3 - 113334 + 113333 3 @@ -17898,7 +18192,7 @@ 1 2 - 4291398 + 4291391 2 @@ -17919,7 +18213,7 @@ 1 2 - 4365920 + 4365913 @@ -17935,7 +18229,7 @@ 1 2 - 4291398 + 4291391 2 @@ -17956,7 +18250,7 @@ 1 2 - 4349931 + 4349923 2 @@ -17971,15 +18265,15 @@ property_location - 4890676 + 4890667 id - 4879894 + 4879885 loc - 8048 + 8027 @@ -17993,7 +18287,7 @@ 1 2 - 4872127 + 4872118 2 @@ -18014,67 +18308,72 @@ 1 5 - 694 + 650 5 - 11 - 737 - - - 11 - 22 + 10 607 - 22 - 37 - 607 - - - 37 - 53 + 10 + 18 629 - 53 - 96 + 18 + 34 607 - 96 - 139 + 34 + 49 607 - 141 - 214 + 49 + 81 607 - 214 - 291 + 82 + 126 607 - 292 - 393 + 127 + 187 607 - 409 - 912 + 188 + 272 607 - 921 - 2270 + 272 + 359 607 - 2333 + 369 + 750 + 607 + + + 759 + 1795 + 607 + + + 1886 + 9614 + 607 + + + 9940 12699 - 520 + 65 @@ -18333,7 +18632,7 @@ 1 2 - 72463 + 72462 2 @@ -18695,11 +18994,11 @@ accessors - 5815073 + 5815063 id - 5815073 + 5815063 kind @@ -18707,15 +19006,15 @@ name - 1544393 + 1544390 declaring_member_id - 4956672 + 4956663 unbound_id - 5171668 + 5171659 @@ -18729,7 +19028,7 @@ 1 2 - 5815073 + 5815063 @@ -18745,7 +19044,7 @@ 1 2 - 5815073 + 5815063 @@ -18761,7 +19060,7 @@ 1 2 - 5815073 + 5815063 @@ -18777,7 +19076,7 @@ 1 2 - 5815073 + 5815063 @@ -18877,7 +19176,7 @@ 1 2 - 1004407 + 1004406 2 @@ -18913,7 +19212,7 @@ 1 2 - 1544393 + 1544390 @@ -18929,7 +19228,7 @@ 1 2 - 1004407 + 1004406 2 @@ -18965,12 +19264,12 @@ 1 2 - 1015298 + 1015296 2 3 - 249556 + 249555 3 @@ -19001,12 +19300,12 @@ 1 2 - 4098271 + 4098263 2 3 - 858401 + 858399 @@ -19022,12 +19321,12 @@ 1 2 - 4098271 + 4098263 2 3 - 858401 + 858399 @@ -19043,12 +19342,12 @@ 1 2 - 4098271 + 4098263 2 3 - 858401 + 858399 @@ -19064,12 +19363,12 @@ 1 2 - 4098271 + 4098263 2 3 - 858401 + 858399 @@ -19085,12 +19384,12 @@ 1 2 - 5083717 + 5083708 2 1206 - 87951 + 87950 @@ -19106,7 +19405,7 @@ 1 2 - 5171668 + 5171659 @@ -19122,7 +19421,7 @@ 1 2 - 5171668 + 5171659 @@ -19138,12 +19437,12 @@ 1 2 - 5083717 + 5083708 2 1206 - 87951 + 87950 @@ -19164,15 +19463,15 @@ accessor_location - 5828090 + 5828080 id - 5815073 + 5815063 loc - 8048 + 8027 @@ -19186,7 +19485,7 @@ 1 2 - 5805202 + 5805192 2 @@ -19207,67 +19506,67 @@ 1 6 - 694 + 650 6 - 13 - 715 - - - 13 - 26 - 629 - - - 26 - 43 + 12 607 - 44 - 68 + 12 + 22 607 - 68 - 106 + 22 + 38 + 650 + + + 38 + 66 + 672 + + + 67 + 105 607 - 116 - 167 + 105 + 161 607 - 168 - 273 - 629 - - - 275 - 373 + 164 + 269 607 - 373 - 492 + 269 + 361 607 - 517 - 1154 + 364 + 464 607 - 1167 - 2661 + 477 + 1105 607 - 2853 + 1105 + 2387 + 607 + + + 2455 13984 - 520 + 585 @@ -19802,7 +20101,7 @@ 1 2 - 50050 + 50049 2 @@ -19839,7 +20138,7 @@ 1 2 - 50050 + 50049 2 @@ -19860,7 +20159,7 @@ 1 2 - 51547 + 51546 2 @@ -20318,7 +20617,7 @@ 1 2 - 100100 + 100099 2 @@ -20371,7 +20670,7 @@ 1 2 - 100100 + 100099 2 @@ -20479,11 +20778,11 @@ operators - 807643 + 807641 id - 807643 + 807641 name @@ -20495,7 +20794,7 @@ declaring_type_id - 94480 + 94479 type_id @@ -20517,7 +20816,7 @@ 1 2 - 807643 + 807641 @@ -20533,7 +20832,7 @@ 1 2 - 807643 + 807641 @@ -20549,7 +20848,7 @@ 1 2 - 807643 + 807641 @@ -20565,7 +20864,7 @@ 1 2 - 807643 + 807641 @@ -20581,7 +20880,7 @@ 1 2 - 807643 + 807641 @@ -21148,7 +21447,7 @@ 1 2 - 92172 + 92171 2 @@ -21169,7 +21468,7 @@ 1 2 - 92172 + 92171 2 @@ -21606,11 +21905,11 @@ operator_location - 1510292 + 1510289 id - 751074 + 751073 loc @@ -21633,7 +21932,7 @@ 2 3 - 740026 + 740024 3 @@ -21672,9 +21971,9 @@ 1880 - 63 + 62 73 - 1859 + 1880 75 @@ -21688,8 +21987,8 @@ 96 - 20093 - 897 + 18513 + 876 @@ -21699,15 +21998,15 @@ constant_value - 2847105 + 2847100 id - 2845825 + 2845820 value - 965573 + 965572 @@ -21721,7 +22020,7 @@ 1 2 - 2844979 + 2844974 2 @@ -21742,7 +22041,7 @@ 1 2 - 780581 + 780580 2 @@ -21767,27 +22066,27 @@ methods - 15027131 + 15027104 id - 15027131 + 15027104 name - 4232388 + 4232381 declaring_type_id - 3140811 + 3140805 type_id - 999548 + 999546 unbound_id - 12416413 + 12416391 @@ -21801,7 +22100,7 @@ 1 2 - 15027131 + 15027104 @@ -21817,7 +22116,7 @@ 1 2 - 15027131 + 15027104 @@ -21833,7 +22132,7 @@ 1 2 - 15027131 + 15027104 @@ -21849,7 +22148,7 @@ 1 2 - 15027131 + 15027104 @@ -21865,22 +22164,22 @@ 1 2 - 3032748 + 3032743 2 3 - 495706 + 495705 3 5 - 336878 + 336877 5 26 - 319392 + 319391 26 @@ -21901,17 +22200,17 @@ 1 2 - 3164935 + 3164930 2 3 - 431663 + 431662 3 6 - 378510 + 378509 6 @@ -21932,12 +22231,12 @@ 1 2 - 3856394 + 3856388 2 7 - 323514 + 323513 7 @@ -21958,22 +22257,22 @@ 1 2 - 3079284 + 3079278 2 3 - 510241 + 510240 3 5 - 336444 + 336443 5 8458 - 306418 + 306417 @@ -21989,12 +22288,12 @@ 1 2 - 1095786 + 1095784 2 3 - 701525 + 701524 3 @@ -22014,12 +22313,12 @@ 6 9 - 274635 + 274634 9 18 - 241659 + 241658 18 @@ -22040,17 +22339,17 @@ 1 2 - 1137440 + 1137438 2 3 - 725802 + 725800 3 4 - 320845 + 320844 4 @@ -22065,12 +22364,12 @@ 6 10 - 265567 + 265566 10 70 - 235693 + 235692 70 @@ -22091,12 +22390,12 @@ 1 2 - 1500895 + 1500892 2 3 - 768953 + 768951 3 @@ -22106,7 +22405,7 @@ 4 5 - 257670 + 257669 5 @@ -22116,7 +22415,7 @@ 10 848 - 62351 + 62350 @@ -22132,12 +22431,12 @@ 1 2 - 1095808 + 1095806 2 3 - 701503 + 701502 3 @@ -22157,12 +22456,12 @@ 6 9 - 274635 + 274634 9 18 - 241659 + 241658 18 @@ -22183,7 +22482,7 @@ 1 2 - 566843 + 566842 2 @@ -22224,7 +22523,7 @@ 1 2 - 697078 + 697076 2 @@ -22260,7 +22559,7 @@ 1 2 - 648915 + 648914 2 @@ -22296,7 +22595,7 @@ 1 2 - 568861 + 568860 2 @@ -22337,12 +22636,12 @@ 1 2 - 12025102 + 12025081 2 3017 - 391310 + 391309 @@ -22358,7 +22657,7 @@ 1 2 - 12416413 + 12416391 @@ -22374,7 +22673,7 @@ 1 2 - 12025189 + 12025167 2 @@ -22395,12 +22694,12 @@ 1 2 - 12291928 + 12291906 2 1636 - 124485 + 124484 @@ -22410,15 +22709,15 @@ method_location - 15099549 + 15099522 id - 15027131 + 15027104 loc - 8526 + 8504 @@ -22432,7 +22731,7 @@ 1 2 - 14977211 + 14977184 2 @@ -22458,7 +22757,7 @@ 6 22 - 672 + 650 23 @@ -22523,23 +22822,23 @@ constructors - 4401500 + 4401492 id - 4401500 + 4401492 name - 2051728 + 2051724 declaring_type_id - 3294779 + 3294773 unbound_id - 4086621 + 4086613 @@ -22553,7 +22852,7 @@ 1 2 - 4401500 + 4401492 @@ -22569,7 +22868,7 @@ 1 2 - 4401500 + 4401492 @@ -22585,7 +22884,7 @@ 1 2 - 4401500 + 4401492 @@ -22601,17 +22900,17 @@ 1 2 - 1486728 + 1486725 2 3 - 373000 + 372999 3 7 - 156767 + 156766 7 @@ -22632,7 +22931,7 @@ 1 2 - 1877995 + 1877992 2 @@ -22658,12 +22957,12 @@ 1 2 - 1508922 + 1508919 2 3 - 374193 + 374192 3 @@ -22689,17 +22988,17 @@ 1 2 - 2455035 + 2455031 2 3 - 711700 + 711699 3 55 - 128043 + 128042 @@ -22715,7 +23014,7 @@ 1 2 - 3294779 + 3294773 @@ -22731,17 +23030,17 @@ 1 2 - 2455035 + 2455031 2 3 - 711700 + 711699 3 55 - 128043 + 128042 @@ -22757,7 +23056,7 @@ 1 2 - 4045053 + 4045046 2 @@ -22778,7 +23077,7 @@ 1 2 - 4086621 + 4086613 @@ -22794,7 +23093,7 @@ 1 2 - 4045053 + 4045046 2 @@ -22809,11 +23108,11 @@ constructor_location - 4437817 + 4437809 id - 4401500 + 4401492 loc @@ -22831,7 +23130,7 @@ 1 2 - 4386878 + 4386870 2 @@ -23226,15 +23525,15 @@ overrides - 3549976 + 3549970 id - 3549976 + 3549970 base_id - 1153191 + 1153189 @@ -23248,7 +23547,7 @@ 1 2 - 3549976 + 3549970 @@ -23264,12 +23563,12 @@ 1 2 - 787090 + 787088 2 3 - 181586 + 181585 3 @@ -23294,11 +23593,11 @@ explicitly_implements - 1340287 + 1340285 id - 1339875 + 1339873 interface_id @@ -23316,7 +23615,7 @@ 1 2 - 1339463 + 1339461 2 @@ -23668,15 +23967,15 @@ local_function_stmts - 3317 + 3316 fn - 3317 + 3316 stmt - 3317 + 3316 @@ -23690,7 +23989,7 @@ 1 2 - 3317 + 3316 @@ -23706,7 +24005,7 @@ 1 2 - 3317 + 3316 @@ -23716,11 +24015,11 @@ fields - 11002601 + 11002581 id - 11002601 + 11002581 kind @@ -23728,19 +24027,19 @@ name - 4569136 + 4569128 declaring_type_id - 2488012 + 2488007 type_id - 2180552 + 2180548 unbound_id - 10641880 + 10641861 @@ -23754,7 +24053,7 @@ 1 2 - 11002601 + 11002581 @@ -23770,7 +24069,7 @@ 1 2 - 11002601 + 11002581 @@ -23786,7 +24085,7 @@ 1 2 - 11002601 + 11002581 @@ -23802,7 +24101,7 @@ 1 2 - 11002601 + 11002581 @@ -23818,7 +24117,7 @@ 1 2 - 11002601 + 11002581 @@ -23939,17 +24238,17 @@ 1 2 - 3598616 + 3598609 2 3 - 510458 + 510457 3 8 - 343495 + 343494 8 @@ -23970,7 +24269,7 @@ 1 2 - 4464307 + 4464299 2 @@ -23991,17 +24290,17 @@ 1 2 - 3598616 + 3598609 2 3 - 510480 + 510479 3 8 - 343473 + 343472 8 @@ -24022,7 +24321,7 @@ 1 2 - 4006545 + 4006538 2 @@ -24048,17 +24347,17 @@ 1 2 - 3622827 + 3622821 2 3 - 511717 + 511716 3 10 - 352368 + 352367 10 @@ -24079,12 +24378,12 @@ 1 2 - 686274 + 686272 2 3 - 636267 + 636266 3 @@ -24094,7 +24393,7 @@ 4 5 - 217773 + 217772 5 @@ -24104,17 +24403,17 @@ 6 8 - 181803 + 181802 8 15 - 193670 + 193669 15 6823 - 72873 + 72872 @@ -24130,7 +24429,7 @@ 1 2 - 2338469 + 2338465 2 @@ -24151,22 +24450,22 @@ 1 2 - 686274 + 686272 2 3 - 636289 + 636287 3 4 - 353236 + 353235 4 5 - 217773 + 217772 5 @@ -24176,17 +24475,17 @@ 6 8 - 181803 + 181802 8 15 - 193670 + 193669 15 6823 - 72873 + 72872 @@ -24202,12 +24501,12 @@ 1 2 - 948001 + 947999 2 3 - 690981 + 690980 3 @@ -24222,7 +24521,7 @@ 5 8 - 228447 + 228446 8 @@ -24243,12 +24542,12 @@ 1 2 - 686274 + 686272 2 3 - 636267 + 636266 3 @@ -24258,7 +24557,7 @@ 4 5 - 217773 + 217772 5 @@ -24268,17 +24567,17 @@ 6 8 - 181803 + 181802 8 15 - 193670 + 193669 15 6823 - 72873 + 72872 @@ -24294,7 +24593,7 @@ 1 2 - 1482497 + 1482495 2 @@ -24330,7 +24629,7 @@ 1 2 - 2117246 + 2117242 2 @@ -24351,12 +24650,12 @@ 1 2 - 1587652 + 1587650 2 3 - 258950 + 258949 3 @@ -24382,7 +24681,7 @@ 1 2 - 1645773 + 1645770 2 @@ -24413,17 +24712,17 @@ 1 2 - 1486142 + 1486139 2 3 - 270687 + 270686 3 5 - 199354 + 199353 5 @@ -24449,7 +24748,7 @@ 1 2 - 10580071 + 10580052 2 @@ -24470,7 +24769,7 @@ 1 2 - 10641880 + 10641861 @@ -24486,7 +24785,7 @@ 1 2 - 10641880 + 10641861 @@ -24502,7 +24801,7 @@ 1 2 - 10580071 + 10580052 2 @@ -24523,7 +24822,7 @@ 1 2 - 10622637 + 10622618 2 @@ -24538,15 +24837,15 @@ field_location - 10994335 + 10994315 id - 10929771 + 10929752 loc - 8265 + 8244 @@ -24560,7 +24859,7 @@ 1 2 - 10890872 + 10890853 2 @@ -24581,7 +24880,7 @@ 1 10 - 650 + 629 10 @@ -24656,11 +24955,11 @@ localvars - 354447 + 354446 id - 354447 + 354446 kind @@ -24680,7 +24979,7 @@ parent_id - 354447 + 354446 @@ -24694,7 +24993,7 @@ 1 2 - 354447 + 354446 @@ -24710,7 +25009,7 @@ 1 2 - 354447 + 354446 @@ -24726,7 +25025,7 @@ 1 2 - 354447 + 354446 @@ -24742,7 +25041,7 @@ 1 2 - 354447 + 354446 @@ -24758,7 +25057,7 @@ 1 2 - 354447 + 354446 @@ -25299,7 +25598,7 @@ 1 2 - 354447 + 354446 @@ -25315,7 +25614,7 @@ 1 2 - 354447 + 354446 @@ -25331,7 +25630,7 @@ 1 2 - 354447 + 354446 @@ -25347,7 +25646,7 @@ 1 2 - 354447 + 354446 @@ -25363,7 +25662,7 @@ 1 2 - 354447 + 354446 @@ -25373,15 +25672,15 @@ localvar_location - 354447 + 354446 id - 354447 + 354446 loc - 354447 + 354446 @@ -25395,7 +25694,7 @@ 1 2 - 354447 + 354446 @@ -25411,7 +25710,7 @@ 1 2 - 354447 + 354446 @@ -25421,19 +25720,19 @@ params - 27466281 + 27466231 id - 27466281 + 27466231 name - 1613730 + 1613727 type_id - 2077566 + 2077562 index @@ -25445,11 +25744,11 @@ parent_id - 15223817 + 15223790 unbound_id - 22123570 + 22123530 @@ -25463,7 +25762,7 @@ 1 2 - 27466281 + 27466231 @@ -25479,7 +25778,7 @@ 1 2 - 27466281 + 27466231 @@ -25495,7 +25794,7 @@ 1 2 - 27466281 + 27466231 @@ -25511,7 +25810,7 @@ 1 2 - 27466281 + 27466231 @@ -25527,7 +25826,7 @@ 1 2 - 27466281 + 27466231 @@ -25543,7 +25842,7 @@ 1 2 - 27466281 + 27466231 @@ -25559,7 +25858,7 @@ 1 2 - 721137 + 721136 2 @@ -25605,12 +25904,12 @@ 1 2 - 1310934 + 1310932 2 3 - 157331 + 157330 3 @@ -25636,7 +25935,7 @@ 1 2 - 1115941 + 1115939 2 @@ -25651,7 +25950,7 @@ 4 21 - 115113 + 115112 @@ -25667,7 +25966,7 @@ 1 2 - 1492260 + 1492257 2 @@ -25693,7 +25992,7 @@ 1 2 - 721137 + 721136 2 @@ -25739,7 +26038,7 @@ 1 2 - 736237 + 736236 2 @@ -25749,12 +26048,12 @@ 3 4 - 146896 + 146895 4 6 - 147742 + 147741 6 @@ -25785,22 +26084,22 @@ 1 2 - 1018379 + 1018377 2 3 - 301667 + 301666 3 4 - 173277 + 173276 4 5 - 129106 + 129105 5 @@ -25810,7 +26109,7 @@ 8 19 - 161171 + 161170 19 @@ -25831,7 +26130,7 @@ 1 2 - 1396976 + 1396974 2 @@ -25841,7 +26140,7 @@ 3 4 - 149456 + 149455 4 @@ -25867,7 +26166,7 @@ 1 2 - 1515539 + 1515536 2 @@ -25898,7 +26197,7 @@ 1 2 - 1956596 + 1956592 2 @@ -25919,17 +26218,17 @@ 1 2 - 1049359 + 1049357 2 3 - 281903 + 281902 3 4 - 174123 + 174122 4 @@ -25939,17 +26238,17 @@ 5 9 - 182085 + 182084 9 24 - 157483 + 157482 24 74138 - 105220 + 105219 @@ -25965,12 +26264,12 @@ 1 2 - 1024605 + 1024603 2 3 - 302795 + 302794 3 @@ -26603,22 +26902,22 @@ 1 2 - 8608267 + 8608252 2 3 - 3845113 + 3845106 3 4 - 1492846 + 1492843 4 8 - 1153842 + 1153840 8 @@ -26639,22 +26938,22 @@ 1 2 - 8608246 + 8608230 2 3 - 3845113 + 3845106 3 4 - 1492846 + 1492843 4 8 - 1153863 + 1153861 8 @@ -26675,22 +26974,22 @@ 1 2 - 9102195 + 9102178 2 3 - 3783500 + 3783493 3 4 - 1384350 + 1384347 4 43 - 953771 + 953770 @@ -26706,22 +27005,22 @@ 1 2 - 8608267 + 8608252 2 3 - 3845113 + 3845106 3 4 - 1492846 + 1492843 4 8 - 1153842 + 1153840 8 @@ -26742,12 +27041,12 @@ 1 2 - 14543531 + 14543505 2 5 - 680286 + 680285 @@ -26763,22 +27062,22 @@ 1 2 - 8608267 + 8608252 2 3 - 3845113 + 3845106 3 4 - 1492846 + 1492843 4 8 - 1153842 + 1153840 8 @@ -26799,12 +27098,12 @@ 1 2 - 21382863 + 21382825 2 17584 - 740706 + 740705 @@ -26820,7 +27119,7 @@ 1 2 - 22123505 + 22123465 2 @@ -26841,12 +27140,12 @@ 1 2 - 21899331 + 21899292 2 9835 - 224238 + 224237 @@ -26862,7 +27161,7 @@ 1 2 - 22123570 + 22123530 @@ -26878,7 +27177,7 @@ 1 2 - 22123570 + 22123530 @@ -26894,12 +27193,12 @@ 1 2 - 21382863 + 21382825 2 17584 - 740706 + 740705 @@ -26909,11 +27208,11 @@ param_location - 27592957 + 27592908 id - 27465934 + 27465884 loc @@ -26931,7 +27230,7 @@ 1 2 - 27379957 + 27379908 2 @@ -27376,11 +27675,11 @@ stmt_parent_top_level - 249938 + 249937 stmt - 249938 + 249937 index @@ -27388,7 +27687,7 @@ parent - 171227 + 171226 @@ -27402,7 +27701,7 @@ 1 2 - 249938 + 249937 @@ -27418,7 +27717,7 @@ 1 2 - 249938 + 249937 @@ -27466,7 +27765,7 @@ 1 2 - 106304 + 106303 2 @@ -27497,7 +27796,7 @@ 1 2 - 171227 + 171226 @@ -27965,11 +28264,11 @@ expressions - 6684214 + 6684202 id - 6684214 + 6684202 kind @@ -27991,7 +28290,7 @@ 1 2 - 6684214 + 6684202 @@ -28007,7 +28306,7 @@ 1 2 - 6684214 + 6684202 @@ -28256,11 +28555,11 @@ expr_parent - 6472330 + 6472322 expr - 6472330 + 6472322 index @@ -28268,7 +28567,7 @@ parent - 4333969 + 4333965 @@ -28282,7 +28581,7 @@ 1 2 - 6472330 + 6472322 @@ -28298,7 +28597,7 @@ 1 2 - 6472330 + 6472322 @@ -28343,7 +28642,7 @@ 66 - 3205676 + 3205672 489 @@ -28389,7 +28688,7 @@ 66 - 3205676 + 3205672 489 @@ -28411,7 +28710,7 @@ 2 3 - 1302939 + 1302935 3 @@ -28437,7 +28736,7 @@ 2 3 - 1302939 + 1302935 3 @@ -28452,11 +28751,11 @@ expr_parent_top_level - 4527928 + 4527920 expr - 4527928 + 4527920 index @@ -28464,7 +28763,7 @@ parent - 4069954 + 4069947 @@ -28478,7 +28777,7 @@ 1 2 - 4527928 + 4527920 @@ -28494,7 +28793,7 @@ 1 2 - 4527928 + 4527920 @@ -28562,7 +28861,7 @@ 1 2 - 3716443 + 3716436 2 @@ -28588,7 +28887,7 @@ 1 2 - 3726770 + 3726764 2 @@ -28603,11 +28902,11 @@ implicitly_typed_array_creation - 19612 + 19611 id - 19612 + 19611 @@ -28695,26 +28994,26 @@ expr_compiler_generated - 6677184 + 6677172 id - 6677184 + 6677172 expr_value - 5479091 + 5479081 id - 5479091 + 5479081 value - 203506 + 203505 @@ -28728,7 +29027,7 @@ 1 2 - 5479091 + 5479081 @@ -28779,15 +29078,15 @@ expr_call - 1125746 + 1125744 caller_id - 1125746 + 1125744 target_id - 895583 + 895582 @@ -28801,7 +29100,7 @@ 1 2 - 1125746 + 1125744 @@ -28817,7 +29116,7 @@ 1 2 - 893788 + 893787 2 @@ -28910,15 +29209,15 @@ expr_location - 6684214 + 6684202 id - 6684214 + 6684202 loc - 5325109 + 5325100 @@ -28932,7 +29231,7 @@ 1 2 - 6684214 + 6684202 @@ -28948,12 +29247,12 @@ 1 2 - 4609547 + 4609539 2 3 - 691472 + 691471 3 @@ -29057,11 +29356,11 @@ expr_argument - 1381112 + 1381083 id - 1381112 + 1381083 mode @@ -29079,7 +29378,7 @@ 1 2 - 1381112 + 1381083 @@ -29120,11 +29419,11 @@ expr_argument_name - 537620 + 537619 id - 537620 + 537619 name @@ -29142,7 +29441,7 @@ 1 2 - 537620 + 537619 @@ -29223,11 +29522,11 @@ xmlEncoding - 476428 + 476427 id - 476428 + 476427 encoding @@ -29245,7 +29544,7 @@ 1 2 - 476428 + 476427 @@ -29739,11 +30038,11 @@ xmlElements - 1042734675 + 1042732803 id - 1042734675 + 1042732803 name @@ -29751,15 +30050,15 @@ parentid - 385731802 + 385731109 idx - 1630081 + 1630078 fileid - 476089 + 476088 @@ -29773,7 +30072,7 @@ 1 2 - 1042734675 + 1042732803 @@ -29789,7 +30088,7 @@ 1 2 - 1042734675 + 1042732803 @@ -29805,7 +30104,7 @@ 1 2 - 1042734675 + 1042732803 @@ -29821,7 +30120,7 @@ 1 2 - 1042734675 + 1042732803 @@ -29919,7 +30218,7 @@ 1 2 - 180311 + 180310 2 @@ -29950,7 +30249,7 @@ 1 2 - 171338 + 171337 2 @@ -29991,32 +30290,32 @@ 1 2 - 187348969 + 187348633 2 3 - 87399822 + 87399665 3 4 - 39675923 + 39675851 4 5 - 25725419 + 25725373 5 8 - 33529933 + 33529873 8 9629 - 12051732 + 12051711 @@ -30032,27 +30331,27 @@ 1 2 - 244194247 + 244193809 2 3 - 69983618 + 69983493 3 4 - 32247777 + 32247719 4 5 - 25493131 + 25493085 5 110 - 13813026 + 13813001 @@ -30068,32 +30367,32 @@ 1 2 - 187348969 + 187348633 2 3 - 87399822 + 87399665 3 4 - 39675923 + 39675851 4 5 - 25725419 + 25725373 5 8 - 33529933 + 33529873 8 9629 - 12051732 + 12051711 @@ -30109,7 +30408,7 @@ 1 2 - 385731802 + 385731109 @@ -30130,12 +30429,12 @@ 3 4 - 626602 + 626601 4 5 - 217897 + 217896 6 @@ -30160,7 +30459,7 @@ 141 322 - 123255 + 123254 322 @@ -30181,7 +30480,7 @@ 1 2 - 1566422 + 1566419 2 @@ -30207,12 +30506,12 @@ 3 4 - 626602 + 626601 4 5 - 217897 + 217896 6 @@ -30237,7 +30536,7 @@ 141 322 - 123255 + 123254 322 @@ -30263,12 +30562,12 @@ 3 4 - 626602 + 626601 4 5 - 217897 + 217896 6 @@ -30293,7 +30592,7 @@ 141 322 - 123255 + 123254 322 @@ -30405,12 +30704,12 @@ 7 9 - 24888 + 24887 9 11 - 43681 + 43680 11 @@ -30557,7 +30856,7 @@ 51 101 - 39279 + 39278 102 @@ -30602,15 +30901,15 @@ xmlAttrs - 782957811 + 782956405 id - 782957811 + 782956405 elementid - 772812975 + 772811588 name @@ -30618,7 +30917,7 @@ value - 16557651 + 16557621 idx @@ -30626,7 +30925,7 @@ fileid - 469994 + 469993 @@ -30640,7 +30939,7 @@ 1 2 - 782957811 + 782956405 @@ -30656,7 +30955,7 @@ 1 2 - 782957811 + 782956405 @@ -30672,7 +30971,7 @@ 1 2 - 782957811 + 782956405 @@ -30688,7 +30987,7 @@ 1 2 - 782957811 + 782956405 @@ -30704,7 +31003,7 @@ 1 2 - 782957811 + 782956405 @@ -30720,12 +31019,12 @@ 1 2 - 767714315 + 767712937 2 13 - 5098660 + 5098651 @@ -30741,12 +31040,12 @@ 1 2 - 767714315 + 767712937 2 13 - 5098660 + 5098651 @@ -30762,12 +31061,12 @@ 1 2 - 767717701 + 767716323 2 13 - 5095274 + 5095264 @@ -30783,12 +31082,12 @@ 1 2 - 767714315 + 767712937 2 13 - 5098660 + 5098651 @@ -30804,7 +31103,7 @@ 1 2 - 772812975 + 772811588 @@ -31105,42 +31404,42 @@ 1 2 - 4011882 + 4011875 2 3 - 1419294 + 1419292 3 4 - 5374629 + 5374619 4 6 - 795909 + 795907 6 8 - 1488541 + 1488538 8 27 - 1245586 + 1245584 27 90 - 1243047 + 1243044 90 214809 - 978759 + 978758 @@ -31156,42 +31455,42 @@ 1 2 - 4012898 + 4012891 2 3 - 1419125 + 1419123 3 4 - 5374968 + 5374958 4 6 - 797094 + 797092 6 8 - 1488033 + 1488030 8 27 - 1244062 + 1244060 27 90 - 1242877 + 1242875 90 214809 - 978590 + 978588 @@ -31207,12 +31506,12 @@ 1 2 - 14765543 + 14765517 2 3 - 1766203 + 1766200 3 @@ -31233,7 +31532,7 @@ 1 2 - 16464702 + 16464672 2 @@ -31254,37 +31553,37 @@ 1 2 - 4652030 + 4652021 2 3 - 1284019 + 1284016 3 4 - 6041188 + 6041177 4 6 - 779994 + 779992 6 8 - 1312293 + 1312291 8 44 - 1256930 + 1256927 44 1527 - 1231195 + 1231193 @@ -31685,7 +31984,7 @@ 711 1058 - 35385 + 35384 1065 @@ -31741,7 +32040,7 @@ 12 44 - 35385 + 35384 44 @@ -31807,7 +32106,7 @@ 2 3 - 196226 + 196225 3 @@ -31817,12 +32116,12 @@ 4 5 - 24888 + 24887 5 6 - 45882 + 45881 6 @@ -31858,7 +32157,7 @@ 4 7 - 35385 + 35384 7 @@ -31883,7 +32182,7 @@ 131 209 - 35385 + 35384 210 @@ -31929,12 +32228,12 @@ 1 2 - 300857 + 300856 2 3 - 35385 + 35384 3 @@ -31959,7 +32258,7 @@ xmlNs - 27089 + 27088 id @@ -32345,11 +32644,11 @@ xmlHasNs - 513336 + 513335 elementId - 513336 + 513335 nsId @@ -32371,7 +32670,7 @@ 1 2 - 513336 + 513335 @@ -32387,7 +32686,7 @@ 1 2 - 513336 + 513335 @@ -32756,7 +33055,7 @@ 1 2 - 133244 + 133243 2 @@ -32818,7 +33117,7 @@ 1 2 - 74664 + 74663 2 @@ -32921,7 +33220,7 @@ 2 3 - 8296 + 8295 3 @@ -32992,19 +33291,19 @@ xmlChars - 808544061 + 808542609 id - 808544061 + 808542609 text - 49726793 + 49726704 parentid - 487106000 + 487105125 idx @@ -33016,7 +33315,7 @@ fileid - 448831 + 448830 @@ -33030,7 +33329,7 @@ 1 2 - 808544061 + 808542609 @@ -33046,7 +33345,7 @@ 1 2 - 808544061 + 808542609 @@ -33062,7 +33361,7 @@ 1 2 - 808544061 + 808542609 @@ -33078,7 +33377,7 @@ 1 2 - 808544061 + 808542609 @@ -33094,7 +33393,7 @@ 1 2 - 808544061 + 808542609 @@ -33110,57 +33409,57 @@ 1 2 - 6839129 + 6839117 2 3 - 2738529 + 2738525 3 4 - 10689155 + 10689136 4 6 - 3529021 + 3529014 6 7 - 4911407 + 4911398 7 9 - 3937218 + 3937211 9 10 - 893260 + 893258 10 11 - 7086485 + 7086473 11 20 - 3458928 + 3458922 20 49 - 3805837 + 3805830 49 250680 - 1837820 + 1837816 @@ -33176,57 +33475,57 @@ 1 2 - 6839975 + 6839963 2 3 - 2739545 + 2739540 3 4 - 10692880 + 10692860 4 6 - 3530375 + 3530369 6 7 - 4916317 + 4916308 7 9 - 3942128 + 3942121 9 10 - 893937 + 893935 10 11 - 7101554 + 7101541 11 20 - 3452833 + 3452827 20 49 - 3788737 + 3788730 49 249267 - 1828508 + 1828505 @@ -33242,12 +33541,12 @@ 1 2 - 48571955 + 48571867 2 32 - 1154838 + 1154836 @@ -33263,7 +33562,7 @@ 1 2 - 49726793 + 49726704 @@ -33279,47 +33578,47 @@ 1 2 - 8926168 + 8926152 2 3 - 2072309 + 2072305 3 4 - 13690110 + 13690085 4 5 - 3843761 + 3843754 5 7 - 4406535 + 4406528 7 9 - 4286497 + 4286490 9 10 - 688060 + 688059 10 11 - 9242432 + 9242416 11 1537 - 2570916 + 2570912 @@ -33335,22 +33634,22 @@ 1 2 - 285652797 + 285652284 2 3 - 137381760 + 137381514 3 4 - 41081842 + 41081769 4 38 - 22989598 + 22989557 @@ -33366,22 +33665,22 @@ 1 2 - 285652797 + 285652284 2 3 - 137537861 + 137537614 3 4 - 41794961 + 41794886 4 28 - 22120380 + 22120340 @@ -33397,22 +33696,22 @@ 1 2 - 285652797 + 285652284 2 3 - 137381760 + 137381514 3 4 - 41081842 + 41081769 4 38 - 22989598 + 22989557 @@ -33428,7 +33727,7 @@ 1 2 - 487104984 + 487104109 2 @@ -33449,7 +33748,7 @@ 1 2 - 487106000 + 487105125 @@ -33966,7 +34265,7 @@ 7 37 - 35385 + 35384 37 @@ -34082,7 +34381,7 @@ 1453 1973 - 39279 + 39278 1995 @@ -34174,7 +34473,7 @@ 1 2 - 447815 + 447814 2 @@ -34189,15 +34488,15 @@ xmllocations - 46972752 + 46972668 xmlElement - 46970079 + 46969994 location - 39595243 + 39595172 @@ -34211,7 +34510,7 @@ 1 2 - 46969994 + 46969909 29 @@ -34232,12 +34531,12 @@ 1 2 - 32374506 + 32374448 2 3 - 7172695 + 7172682 3 @@ -34252,11 +34551,11 @@ commentline - 1227120 + 1227125 id - 1227120 + 1227125 kind @@ -34264,11 +34563,11 @@ text - 47656 + 47658 rawtext - 47745 + 47747 @@ -34282,7 +34581,7 @@ 1 2 - 1227120 + 1227125 @@ -34298,7 +34597,7 @@ 1 2 - 1227120 + 1227125 @@ -34314,7 +34613,7 @@ 1 2 - 1227120 + 1227125 @@ -34333,8 +34632,8 @@ 2 - 6150 - 6151 + 6153 + 6154 2 @@ -34359,8 +34658,8 @@ 2 - 660 - 661 + 661 + 662 2 @@ -34385,8 +34684,8 @@ 2 - 663 - 664 + 664 + 665 2 @@ -34418,7 +34717,7 @@ 3 5 - 4088 + 4091 5 @@ -34444,7 +34743,7 @@ 1 2 - 47649 + 47651 2 @@ -34465,7 +34764,7 @@ 1 2 - 47593 + 47595 2 @@ -34496,7 +34795,7 @@ 3 5 - 4065 + 4067 5 @@ -34522,7 +34821,7 @@ 1 2 - 47745 + 47747 @@ -34538,7 +34837,7 @@ 1 2 - 47745 + 47747 @@ -34548,15 +34847,15 @@ commentline_location - 1227120 + 1227125 id - 1227120 + 1227125 loc - 1227120 + 1227125 @@ -34570,7 +34869,7 @@ 1 2 - 1227120 + 1227125 @@ -34586,7 +34885,7 @@ 1 2 - 1227120 + 1227125 @@ -34596,26 +34895,26 @@ commentblock - 412296 + 412295 id - 412296 + 412295 commentblock_location - 412296 + 412295 id - 412296 + 412295 loc - 412296 + 412295 @@ -34629,7 +34928,7 @@ 1 2 - 412296 + 412295 @@ -34645,7 +34944,7 @@ 1 2 - 412296 + 412295 @@ -34655,15 +34954,15 @@ commentblock_binding - 1601079 + 1601076 id - 412296 + 412295 entity - 415904 + 415903 bindtype @@ -34728,7 +35027,7 @@ 2 3 - 379365 + 379364 3 @@ -34759,7 +35058,7 @@ 3 4 - 345375 + 345374 4 @@ -34836,15 +35135,15 @@ commentblock_child - 1631666 + 1631670 id - 412296 + 412295 commentline - 1227120 + 1227125 index @@ -34893,7 +35192,7 @@ 4 5 - 393790 + 393789 5 @@ -34914,7 +35213,7 @@ 1 2 - 1227120 + 1227125 @@ -34930,12 +35229,12 @@ 1 2 - 822573 + 822579 2 3 - 404546 + 404545 @@ -34985,7 +35284,7 @@ 110 - 177 + 180 7 @@ -35051,7 +35350,7 @@ 110 - 177 + 180 7 @@ -36712,11 +37011,11 @@ cil_instruction - 370458591 + 370457925 id - 370458591 + 370457925 opcode @@ -36724,11 +37023,11 @@ index - 1246869 + 1246867 impl - 17616263 + 17616232 @@ -36742,7 +37041,7 @@ 1 2 - 370458591 + 370457925 @@ -36758,7 +37057,7 @@ 1 2 - 370458591 + 370457925 @@ -36774,7 +37073,7 @@ 1 2 - 370458591 + 370457925 @@ -37028,7 +37327,7 @@ 3 4 - 343039 + 343038 4 @@ -37048,7 +37347,7 @@ 15 16 - 106652 + 106651 16 @@ -37079,7 +37378,7 @@ 1 2 - 523931 + 523930 2 @@ -37140,7 +37439,7 @@ 3 4 - 343039 + 343038 4 @@ -37160,7 +37459,7 @@ 15 16 - 106652 + 106651 16 @@ -37191,57 +37490,57 @@ 1 3 - 1299002 + 1299000 3 4 - 3887982 + 3887975 4 5 - 1827121 + 1827117 5 6 - 1190311 + 1190309 6 8 - 1392724 + 1392721 8 11 - 1390272 + 1390270 11 16 - 1446289 + 1446286 16 23 - 1331978 + 1331976 23 35 - 1364217 + 1364214 35 67 - 1341329 + 1341326 67 57474 - 1145034 + 1145031 @@ -37257,52 +37556,52 @@ 1 3 - 1301671 + 1301668 3 4 - 4029628 + 4029621 4 5 - 2083923 + 2083919 5 6 - 1825211 + 1825208 6 7 - 1176166 + 1176164 7 9 - 1560903 + 1560900 9 12 - 1593163 + 1593160 12 16 - 1494538 + 1494535 16 24 - 1379837 + 1379835 24 77 - 1171219 + 1171217 @@ -37318,57 +37617,57 @@ 1 3 - 1299002 + 1299000 3 4 - 3887982 + 3887975 4 5 - 1827121 + 1827117 5 6 - 1190311 + 1190309 6 8 - 1392724 + 1392721 8 11 - 1390272 + 1390270 11 16 - 1446289 + 1446286 16 23 - 1331978 + 1331976 23 35 - 1364217 + 1364214 35 67 - 1341329 + 1341326 67 57474 - 1145034 + 1145031 @@ -37378,15 +37677,15 @@ cil_jump - 28397577 + 28397526 instruction - 28397577 + 28397526 target - 21559112 + 21559074 @@ -37400,7 +37699,7 @@ 1 2 - 28397577 + 28397526 @@ -37416,17 +37715,17 @@ 1 2 - 17986226 + 17986194 2 3 - 2350922 + 2350917 3 473 - 1221964 + 1221961 @@ -37436,15 +37735,15 @@ cil_access - 150867340 + 150867069 instruction - 150867340 + 150867069 target - 35942622 + 35942557 @@ -37458,7 +37757,7 @@ 1 2 - 150867340 + 150867069 @@ -37474,32 +37773,32 @@ 1 2 - 14815628 + 14815601 2 3 - 9023572 + 9023556 3 4 - 4374403 + 4374395 4 5 - 2253837 + 2253833 5 8 - 3030514 + 3030508 8 72956 - 2444665 + 2444661 @@ -37509,15 +37808,15 @@ cil_value - 14528539 + 14528513 instruction - 14528539 + 14528513 value - 3617230 + 3617224 @@ -37531,7 +37830,7 @@ 1 2 - 14528539 + 14528513 @@ -37547,22 +37846,22 @@ 1 2 - 2708887 + 2708882 2 3 - 497181 + 497180 3 7 - 273507 + 273506 7 182148 - 137654 + 137653 @@ -37572,7 +37871,7 @@ cil_switch - 2990400 + 2990395 instruction @@ -37584,7 +37883,7 @@ target - 1319005 + 1319002 @@ -37792,7 +38091,7 @@ 1 2 - 1301584 + 1301581 2 @@ -37813,7 +38112,7 @@ 1 2 - 1172673 + 1172671 2 @@ -37875,11 +38174,11 @@ cil_type_location - 3557547 + 3557541 id - 3557547 + 3557541 loc @@ -37897,7 +38196,7 @@ 1 2 - 3557547 + 3557541 @@ -37973,11 +38272,11 @@ cil_method_location - 21566771 + 21566732 id - 21566771 + 21566732 loc @@ -37995,7 +38294,7 @@ 1 2 - 21566771 + 21566732 @@ -38086,15 +38385,15 @@ cil_type - 9109571 + 9109554 id - 9109571 + 9109554 name - 2569541 + 2569536 kind @@ -38102,11 +38401,11 @@ parent - 1843609 + 1843605 sourceDecl - 5094760 + 5094751 @@ -38120,7 +38419,7 @@ 1 2 - 9109571 + 9109554 @@ -38136,7 +38435,7 @@ 1 2 - 9109571 + 9109554 @@ -38152,7 +38451,7 @@ 1 2 - 9109571 + 9109554 @@ -38168,7 +38467,7 @@ 1 2 - 9109571 + 9109554 @@ -38184,12 +38483,12 @@ 1 2 - 2257721 + 2257716 2 4 - 215148 + 215147 4 @@ -38210,7 +38509,7 @@ 1 2 - 2569541 + 2569536 @@ -38226,7 +38525,7 @@ 1 2 - 2374656 + 2374652 2 @@ -38252,12 +38551,12 @@ 1 2 - 2346604 + 2346600 2 5 - 199788 + 199787 5 @@ -38417,7 +38716,7 @@ 1 2 - 1199271 + 1199269 2 @@ -38453,7 +38752,7 @@ 1 2 - 1205692 + 1205690 2 @@ -38489,7 +38788,7 @@ 1 2 - 1815145 + 1815142 2 @@ -38510,7 +38809,7 @@ 1 2 - 1205302 + 1205300 2 @@ -38546,7 +38845,7 @@ 1 2 - 4875229 + 4875221 2 @@ -38567,7 +38866,7 @@ 1 2 - 5094760 + 5094751 @@ -38583,7 +38882,7 @@ 1 2 - 5094760 + 5094751 @@ -38599,7 +38898,7 @@ 1 2 - 5022820 + 5022811 2 @@ -38881,23 +39180,23 @@ cil_method - 28926216 + 28926164 id - 28926216 + 28926164 name - 5796090 + 5796080 parent - 5584869 + 5584859 return_type - 2472804 + 2472799 @@ -38911,7 +39210,7 @@ 1 2 - 28926216 + 28926164 @@ -38927,7 +39226,7 @@ 1 2 - 28926216 + 28926164 @@ -38943,7 +39242,7 @@ 1 2 - 28926216 + 28926164 @@ -38959,22 +39258,22 @@ 1 2 - 3864986 + 3864979 2 3 - 884652 + 884650 3 5 - 510719 + 510718 5 19 - 435546 + 435545 19 @@ -38995,17 +39294,17 @@ 1 2 - 4034878 + 4034871 2 3 - 825143 + 825141 3 5 - 474033 + 474032 5 @@ -39031,7 +39330,7 @@ 1 2 - 5227663 + 5227653 2 @@ -39057,37 +39356,37 @@ 1 2 - 1766158 + 1766155 2 3 - 1281082 + 1281080 3 4 - 640779 + 640778 4 5 - 458716 + 458715 5 7 - 476614 + 476613 7 11 - 481235 + 481234 11 39 - 420880 + 420879 39 @@ -39108,17 +39407,17 @@ 1 2 - 1806055 + 1806052 2 3 - 1302170 + 1302167 3 4 - 656703 + 656702 4 @@ -39133,7 +39432,7 @@ 7 11 - 440384 + 440383 11 @@ -39154,17 +39453,17 @@ 1 2 - 2382488 + 2382483 2 3 - 1477464 + 1477462 3 4 - 630605 + 630603 4 @@ -39174,12 +39473,12 @@ 5 7 - 451123 + 451122 7 12757 - 307503 + 307502 @@ -39195,7 +39494,7 @@ 1 2 - 1493649 + 1493646 2 @@ -39215,7 +39514,7 @@ 8 508819 - 175251 + 175250 @@ -39231,17 +39530,17 @@ 1 2 - 1692439 + 1692436 2 3 - 398621 + 398620 3 5 - 201133 + 201132 5 @@ -39262,12 +39561,12 @@ 1 2 - 1616680 + 1616677 2 3 - 413309 + 413308 3 @@ -39292,15 +39591,15 @@ cil_method_source_declaration - 25660941 + 25660895 method - 25660941 + 25660895 source - 22347808 + 22347768 @@ -39314,7 +39613,7 @@ 1 2 - 25660941 + 25660895 @@ -39330,12 +39629,12 @@ 1 2 - 21046744 + 21046706 2 981 - 1301063 + 1301061 @@ -39345,15 +39644,15 @@ cil_method_implementation - 19889366 + 19889330 id - 19889366 + 19889330 method - 19872444 + 19872408 location @@ -39371,7 +39670,7 @@ 1 2 - 19889366 + 19889330 @@ -39387,7 +39686,7 @@ 1 2 - 19889366 + 19889330 @@ -39403,7 +39702,7 @@ 1 2 - 19870318 + 19870282 2 @@ -39424,7 +39723,7 @@ 1 2 - 19872444 + 19872408 @@ -39586,15 +39885,15 @@ cil_implements - 1031396 + 1031394 id - 1030962 + 1030960 decl - 190676 + 190675 @@ -39608,7 +39907,7 @@ 1 2 - 1030528 + 1030526 2 @@ -39659,23 +39958,23 @@ cil_field - 11684992 + 11684971 id - 11684992 + 11684971 parent - 2707933 + 2707928 name - 4586883 + 4586875 field_type - 2250192 + 2250188 @@ -39689,7 +39988,7 @@ 1 2 - 11684992 + 11684971 @@ -39705,7 +40004,7 @@ 1 2 - 11684992 + 11684971 @@ -39721,7 +40020,7 @@ 1 2 - 11684992 + 11684971 @@ -39737,12 +40036,12 @@ 1 2 - 796245 + 796244 2 3 - 671000 + 670999 3 @@ -39752,7 +40051,7 @@ 4 5 - 241095 + 241094 5 @@ -39762,12 +40061,12 @@ 6 8 - 192889 + 192888 8 15 - 209963 + 209962 15 @@ -39788,12 +40087,12 @@ 1 2 - 796245 + 796244 2 3 - 671000 + 670999 3 @@ -39803,7 +40102,7 @@ 4 5 - 241095 + 241094 5 @@ -39813,12 +40112,12 @@ 6 8 - 192889 + 192888 8 15 - 209963 + 209962 15 @@ -39839,12 +40138,12 @@ 1 2 - 917302 + 917301 2 3 - 895521 + 895519 3 @@ -39859,7 +40158,7 @@ 5 8 - 237971 + 237970 8 @@ -39880,12 +40179,12 @@ 1 2 - 3517998 + 3517991 2 3 - 582507 + 582506 3 @@ -39911,12 +40210,12 @@ 1 2 - 3517998 + 3517991 2 3 - 582507 + 582506 3 @@ -39942,7 +40241,7 @@ 1 2 - 4006631 + 4006624 2 @@ -39968,12 +40267,12 @@ 1 2 - 1354823 + 1354821 2 3 - 434331 + 434330 3 @@ -39988,7 +40287,7 @@ 7 58308 - 155422 + 155421 @@ -40004,22 +40303,22 @@ 1 2 - 1515669 + 1515666 2 3 - 436132 + 436131 3 6 - 184992 + 184991 6 22697 - 113399 + 113398 @@ -40035,22 +40334,22 @@ 1 2 - 1648572 + 1648569 2 3 - 261770 + 261769 3 5 - 174839 + 174838 5 33056 - 165011 + 165010 @@ -40060,15 +40359,15 @@ cil_parameter - 55186717 + 55186618 id - 55186717 + 55186618 parameterizable - 27728463 + 27728414 index @@ -40076,7 +40375,7 @@ param_type - 7131258 + 7131245 @@ -40090,7 +40389,7 @@ 1 2 - 55186717 + 55186618 @@ -40106,7 +40405,7 @@ 1 2 - 55186717 + 55186618 @@ -40122,7 +40421,7 @@ 1 2 - 55186717 + 55186618 @@ -40138,22 +40437,22 @@ 1 2 - 12120712 + 12120690 2 3 - 8866306 + 8866290 3 4 - 4255190 + 4255182 4 7 - 2154041 + 2154037 7 @@ -40174,22 +40473,22 @@ 1 2 - 12120712 + 12120690 2 3 - 8866306 + 8866290 3 4 - 4255190 + 4255182 4 7 - 2154041 + 2154037 7 @@ -40210,22 +40509,22 @@ 1 2 - 12478872 + 12478850 2 3 - 9036481 + 9036465 3 4 - 4177088 + 4177081 4 43 - 2036021 + 2036017 @@ -40424,42 +40723,42 @@ 1 2 - 2005301 + 2005297 2 3 - 2103427 + 2103423 3 4 - 781427 + 781426 4 5 - 480433 + 480432 5 7 - 544237 + 544236 7 11 - 540137 + 540136 11 36 - 538857 + 538856 36 108909 - 137437 + 137436 @@ -40475,37 +40774,37 @@ 1 2 - 2033873 + 2033869 2 3 - 2102125 + 2102121 3 4 - 775331 + 775330 4 5 - 473924 + 473923 5 7 - 543586 + 543585 7 11 - 537707 + 537706 11 37 - 535321 + 535320 37 @@ -40526,17 +40825,17 @@ 1 2 - 5015009 + 5015000 2 3 - 1530486 + 1530484 3 6 - 535646 + 535645 6 @@ -40551,37 +40850,37 @@ cil_parameter_in - 263267 + 263266 id - 263267 + 263266 cil_parameter_out - 502431 + 502430 id - 502431 + 502430 cil_setter - 789281 + 789279 prop - 789281 + 789279 method - 789281 + 789279 @@ -40595,7 +40894,7 @@ 1 2 - 789281 + 789279 @@ -40611,7 +40910,7 @@ 1 2 - 789281 + 789279 @@ -40668,7 +40967,7 @@ 1 2 - 144249 + 144248 2 @@ -40837,11 +41136,11 @@ cil_type_annotation - 1287048 + 1287046 id - 1287048 + 1287046 annotation @@ -40859,7 +41158,7 @@ 1 2 - 1287048 + 1287046 @@ -40885,15 +41184,15 @@ cil_getter - 4403800 + 4403792 prop - 4403800 + 4403792 method - 4403800 + 4403792 @@ -40907,7 +41206,7 @@ 1 2 - 4403800 + 4403792 @@ -40923,7 +41222,7 @@ 1 2 - 4403800 + 4403792 @@ -41077,23 +41376,23 @@ cil_property - 4409961 + 4409953 id - 4409961 + 4409953 parent - 1169158 + 1169156 name - 1132082 + 1132080 property_type - 519158 + 519157 @@ -41107,7 +41406,7 @@ 1 2 - 4409961 + 4409953 @@ -41123,7 +41422,7 @@ 1 2 - 4409961 + 4409953 @@ -41139,7 +41438,7 @@ 1 2 - 4409961 + 4409953 @@ -41155,7 +41454,7 @@ 1 2 - 383218 + 383217 2 @@ -41206,7 +41505,7 @@ 2 3 - 214085 + 214084 3 @@ -41221,7 +41520,7 @@ 5 7 - 102660 + 102659 7 @@ -41247,12 +41546,12 @@ 1 2 - 452273 + 452272 2 3 - 353995 + 353994 3 @@ -41288,7 +41587,7 @@ 1 2 - 719380 + 719379 2 @@ -41324,12 +41623,12 @@ 1 2 - 719380 + 719379 2 3 - 187487 + 187486 3 @@ -41344,7 +41643,7 @@ 8 3695 - 66972 + 66971 @@ -41360,7 +41659,7 @@ 1 2 - 989481 + 989479 2 @@ -41427,7 +41726,7 @@ 1 2 - 316029 + 316028 2 @@ -41874,15 +42173,15 @@ cil_local_variable - 16916582 + 16916551 id - 16916582 + 16916551 impl - 4885274 + 4885265 index @@ -41890,7 +42189,7 @@ var_type - 2173089 + 2173085 @@ -41904,7 +42203,7 @@ 1 2 - 16916582 + 16916551 @@ -41920,7 +42219,7 @@ 1 2 - 16916582 + 16916551 @@ -41936,7 +42235,7 @@ 1 2 - 16916582 + 16916551 @@ -41952,37 +42251,37 @@ 1 2 - 1994583 + 1994580 2 3 - 848508 + 848506 3 4 - 575586 + 575585 4 5 - 385691 + 385690 5 6 - 282988 + 282987 6 9 - 410510 + 410509 9 29 - 366448 + 366447 29 @@ -42003,37 +42302,37 @@ 1 2 - 1994583 + 1994580 2 3 - 848508 + 848506 3 4 - 575586 + 575585 4 5 - 385691 + 385690 5 6 - 282988 + 282987 6 9 - 410510 + 410509 9 29 - 366448 + 366447 29 @@ -42054,27 +42353,27 @@ 1 2 - 2184197 + 2184193 2 3 - 934203 + 934201 3 4 - 601577 + 601576 4 5 - 367424 + 367423 5 7 - 394760 + 394759 7 @@ -42258,7 +42557,7 @@ 1 2 - 1379208 + 1379206 2 @@ -42273,12 +42572,12 @@ 4 7 - 171064 + 171063 7 29 - 164317 + 164316 29 @@ -42299,12 +42598,12 @@ 1 2 - 1439672 + 1439669 2 3 - 263506 + 263505 3 @@ -42319,7 +42618,7 @@ 12 44190 - 110058 + 110057 @@ -42335,7 +42634,7 @@ 1 2 - 1482931 + 1482929 2 @@ -42350,7 +42649,7 @@ 4 8 - 175902 + 175901 8 @@ -42418,15 +42717,15 @@ cil_handler - 1747392 + 1747389 id - 1747392 + 1747389 impl - 1140478 + 1140476 index @@ -42438,15 +42737,15 @@ try_start - 1706714 + 1706711 try_end - 1726066 + 1726063 handler_start - 1747392 + 1747389 @@ -42460,7 +42759,7 @@ 1 2 - 1747392 + 1747389 @@ -42476,7 +42775,7 @@ 1 2 - 1747392 + 1747389 @@ -42492,7 +42791,7 @@ 1 2 - 1747392 + 1747389 @@ -42508,7 +42807,7 @@ 1 2 - 1747392 + 1747389 @@ -42524,7 +42823,7 @@ 1 2 - 1747392 + 1747389 @@ -42540,7 +42839,7 @@ 1 2 - 1747392 + 1747389 @@ -42556,7 +42855,7 @@ 1 2 - 839570 + 839568 2 @@ -42587,7 +42886,7 @@ 1 2 - 839570 + 839568 2 @@ -42618,7 +42917,7 @@ 1 2 - 1067865 + 1067863 2 @@ -42639,7 +42938,7 @@ 1 2 - 853172 + 853171 2 @@ -42670,12 +42969,12 @@ 1 2 - 847185 + 847183 2 3 - 179308 + 179307 3 @@ -42701,7 +43000,7 @@ 1 2 - 839570 + 839568 2 @@ -43254,7 +43553,7 @@ 1 2 - 1674736 + 1674733 2 @@ -43275,7 +43574,7 @@ 1 2 - 1706714 + 1706711 @@ -43291,7 +43590,7 @@ 1 2 - 1674736 + 1674733 2 @@ -43312,7 +43611,7 @@ 1 2 - 1694109 + 1694106 2 @@ -43333,7 +43632,7 @@ 1 2 - 1689510 + 1689507 2 @@ -43354,7 +43653,7 @@ 1 2 - 1674736 + 1674733 2 @@ -43375,7 +43674,7 @@ 1 2 - 1709426 + 1709423 2 @@ -43396,7 +43695,7 @@ 1 2 - 1726066 + 1726063 @@ -43412,7 +43711,7 @@ 1 2 - 1709426 + 1709423 2 @@ -43433,7 +43732,7 @@ 1 2 - 1724634 + 1724631 2 @@ -43454,7 +43753,7 @@ 1 2 - 1726066 + 1726063 @@ -43470,7 +43769,7 @@ 1 2 - 1709426 + 1709423 2 @@ -43491,7 +43790,7 @@ 1 2 - 1747392 + 1747389 @@ -43507,7 +43806,7 @@ 1 2 - 1747392 + 1747389 @@ -43523,7 +43822,7 @@ 1 2 - 1747392 + 1747389 @@ -43539,7 +43838,7 @@ 1 2 - 1747392 + 1747389 @@ -43555,7 +43854,7 @@ 1 2 - 1747392 + 1747389 @@ -43571,7 +43870,7 @@ 1 2 - 1747392 + 1747389 @@ -43712,11 +44011,11 @@ cil_method_stack_size - 19888845 + 19888809 method - 19888845 + 19888809 size @@ -43734,7 +44033,7 @@ 1 2 - 19888845 + 19888809 @@ -43805,110 +44104,110 @@ cil_public - 22449297 + 22449256 id - 22449297 + 22449256 cil_private - 11386275 + 11386254 id - 11386275 + 11386254 cil_protected - 21117144 + 21117106 id - 21117144 + 21117106 cil_internal - 725021 + 725019 id - 725021 + 725019 cil_static - 10668456 + 10668437 id - 10668456 + 10668437 cil_sealed - 4672361 + 4672352 id - 4672361 + 4672352 cil_virtual - 8620980 + 8620965 id - 8620980 + 8620965 cil_abstract - 2076286 + 2076282 id - 2076286 + 2076282 cil_class - 3287620 + 3287614 id - 3287620 + 3287614 cil_interface - 269971 + 269970 id - 269971 + 269970 @@ -43937,33 +44236,33 @@ cil_specialname - 9198303 + 9198286 id - 9198303 + 9198286 cil_newslot - 5415106 + 5415097 id - 5415106 + 5415097 cil_base_class - 3276881 + 3276875 id - 3276881 + 3276875 base @@ -43981,7 +44280,7 @@ 1 2 - 3276881 + 3276875 @@ -44027,15 +44326,15 @@ cil_base_interface - 2149528 + 2149524 id - 914265 + 914263 base - 395714 + 395713 @@ -44049,7 +44348,7 @@ 1 2 - 516815 + 516814 2 @@ -44090,7 +44389,7 @@ 1 2 - 263484 + 263483 2 @@ -44208,11 +44507,11 @@ cil_type_parameter - 1302994 + 1302992 unbound - 978091 + 978090 index @@ -44220,7 +44519,7 @@ param - 1302994 + 1302992 @@ -44234,7 +44533,7 @@ 1 2 - 730575 + 730573 2 @@ -44260,7 +44559,7 @@ 1 2 - 730575 + 730573 2 @@ -44408,7 +44707,7 @@ 1 2 - 1302994 + 1302992 @@ -44424,7 +44723,7 @@ 1 2 - 1302994 + 1302992 @@ -44434,11 +44733,11 @@ cil_type_argument - 8232620 + 8232606 bound - 6158785 + 6158774 index @@ -44446,7 +44745,7 @@ t - 2057108 + 2057104 @@ -44460,17 +44759,17 @@ 1 2 - 4348543 + 4348535 2 3 - 1618416 + 1618413 3 43 - 191826 + 191825 @@ -44486,17 +44785,17 @@ 1 2 - 4430311 + 4430303 2 3 - 1586134 + 1586131 3 43 - 142340 + 142339 @@ -44629,12 +44928,12 @@ 1 2 - 889077 + 889076 2 3 - 538076 + 538075 3 @@ -44670,12 +44969,12 @@ 1 2 - 1655948 + 1655945 2 3 - 368856 + 368855 3 @@ -44781,15 +45080,15 @@ cil_attribute - 4315762 + 4315754 attributeid - 4315762 + 4315754 element - 3808557 + 3808550 constructor @@ -44807,7 +45106,7 @@ 1 2 - 4315762 + 4315754 @@ -44823,7 +45122,7 @@ 1 2 - 4315762 + 4315754 @@ -44839,12 +45138,12 @@ 1 2 - 3532186 + 3532180 2 3520 - 276371 + 276370 @@ -44860,7 +45159,7 @@ 1 2 - 3535506 + 3535499 2 @@ -45017,7 +45316,7 @@ cil_attribute_named_argument - 221114 + 221113 attribute_id @@ -45064,7 +45363,7 @@ 1 2 - 104462 + 104461 2 @@ -45233,11 +45532,11 @@ cil_attribute_positional_argument - 1300780 + 1300778 attribute_id - 1270982 + 1270980 index @@ -45259,7 +45558,7 @@ 1 2 - 1243724 + 1243722 2 @@ -45280,12 +45579,12 @@ 1 2 - 1243893 + 1243891 2 4 - 27089 + 27088 @@ -45409,11 +45708,11 @@ metadata_handle - 80614656 + 80614512 entity - 80367053 + 80366908 location @@ -45421,7 +45720,7 @@ handle - 2025043 + 2025039 @@ -45435,7 +45734,7 @@ 1 2 - 80240940 + 80240796 2 @@ -45456,7 +45755,7 @@ 1 2 - 80243283 + 80243139 2 @@ -45634,7 +45933,7 @@ 4 5 - 264981 + 264980 5 @@ -45649,7 +45948,7 @@ 11 15 - 171194 + 171193 15 @@ -45664,7 +45963,7 @@ 25 39 - 158763 + 158762 39 @@ -45700,12 +45999,12 @@ 1 2 - 274505 + 274504 2 3 - 266044 + 266043 3 @@ -45720,7 +46019,7 @@ 6 8 - 171194 + 171193 8 @@ -45750,7 +46049,7 @@ 37 70 - 154207 + 154206 70 @@ -45764,4 +46063,4 @@ - + \ No newline at end of file diff --git a/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme new file mode 100644 index 00000000000..193c35b0e37 --- /dev/null +++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme @@ -0,0 +1,2088 @@ +/* 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); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +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_global( + unique int id: @using_directive ref +); + +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/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme new file mode 100644 index 00000000000..ff083666c7f --- /dev/null +++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme @@ -0,0 +1,2098 @@ +/* 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); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +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_global( + unique int id: @using_directive ref +); + +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, 3: span */ + +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_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int 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/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties new file mode 100644 index 00000000000..31163274055 --- /dev/null +++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties @@ -0,0 +1,2 @@ +description: Add support for line span pragma. +compatibility: backwards diff --git a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql index d3b9135df6e..766fb6d890a 100644 --- a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql +++ b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql @@ -39,6 +39,10 @@ private predicate acceptableShadowing(LocalScopeVariable v, Member m) { ) or t.getAConstructor().getAParameter() = v + or + // Record types have auto-generated Deconstruct methods, which declare an out parameter + // with the same name as the property field(s). + t.(RecordType).getAMethod("Deconstruct").getAParameter() = v ) } diff --git a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql index 900ded8ddb6..4b3fa2096a7 100755 --- a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql +++ b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql @@ -26,11 +26,11 @@ Stmt getASuccessorStmt(Stmt s) { } class IfThenStmt extends IfStmt { - IfThenStmt() { not exists(Stmt s | getElse() = s) } + IfThenStmt() { not exists(getElse()) } } class IfThenElseStmt extends IfStmt { - IfThenElseStmt() { exists(Stmt s | getElse() = s) } + IfThenElseStmt() { exists(getElse()) } } Stmt getTrailingBody(Stmt s) { diff --git a/csharp/ql/src/experimental/ir/internal/IRGuards.qll b/csharp/ql/src/experimental/ir/internal/IRGuards.qll index c5351e14d5e..a87788eb9a0 100644 --- a/csharp/ql/src/experimental/ir/internal/IRGuards.qll +++ b/csharp/ql/src/experimental/ir/internal/IRGuards.qll @@ -24,7 +24,7 @@ class GuardCondition extends Expr { exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression()) or // no binary operators in the IR - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition or // the IR short-circuits if(!x) // don't produce a guard condition for `y = !x` and other non-short-circuited cases @@ -124,7 +124,7 @@ private predicate impliesValue( */ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { GuardConditionFromBinaryLogicalOperator() { - exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) + this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition } override predicate controls(BasicBlock controlled, boolean testIsTrue) { diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmas.cs b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs new file mode 100644 index 00000000000..73fff46f6fc --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs @@ -0,0 +1,12 @@ +using System; + +public class MyLineDirective +{ + public static void M1() + { +#line (1, 1) - (1, 30) 5 "LinePragmasRef1.cs" + int i = 0; +#line (2, 1) - (5, 32) "LinePragmasRef2.cs" + int j = 0; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs b/csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs deleted file mode 100644 index 14dc3d77138..00000000000 --- a/csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System; - -public record MyEntry(string Name, string Address) -{ - sealed public override string ToString() => $"{Name} lives at {Address}"; -}; \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs new file mode 100644 index 00000000000..994e4226927 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs @@ -0,0 +1,12 @@ +using System; + +public record MyEntry(string Name, string Address) +{ + sealed public override string ToString() => $"{Name} lives at {Address}"; +}; + +public record class MyClassRecord(DateTime stuff) { } + +public readonly record struct MyReadonlyRecordStruct(string Stuff) { } + +public record struct MyRecordStruct1(int Stuff) { } diff --git a/csharp/ql/test/library-tests/csharp10/StructTypes.cs b/csharp/ql/test/library-tests/csharp10/StructTypes.cs new file mode 100644 index 00000000000..b337f773337 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/StructTypes.cs @@ -0,0 +1,19 @@ +using System; + +// Struct with user declared parameterless constructor. +public struct MyStructParameterlessConstructor +{ + public int X; + public readonly int Y; + public int Z { get; } + + public MyStructParameterlessConstructor() + { + X = 1; + Y = 2; + Z = 3; + } +} + +// Struct with compiler generated parameterless constructor. +public struct MyDefaultStruct { } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp10/WithExpression.cs b/csharp/ql/test/library-tests/csharp10/WithExpression.cs new file mode 100644 index 00000000000..ba3b219cb91 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/WithExpression.cs @@ -0,0 +1,30 @@ +using System; + +public struct MyStruct +{ + public int X; + public MyStruct(int x) => X = x; +} + +public record struct MyRecordStruct2(int Y) { } + +public class MyWithExamples +{ + public void M1() + { + var s1 = new MyStruct(1); + var s2 = s1 with { X = 2 }; + } + + public void M2() + { + var r1 = new MyRecordStruct2(4); + var r2 = r1 with { Y = 6 }; + } + + public void M3() + { + var anon1 = new { A = 3, B = 4 }; + var anon2 = anon1 with { A = 5 }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.expected b/csharp/ql/test/library-tests/csharp10/linePragmas.expected new file mode 100644 index 00000000000..2d88fa7582f --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/linePragmas.expected @@ -0,0 +1,5 @@ +linespan_directives +| LinePragmas.cs:7:1:7:45 | #line ... | 1 | 1 | 1 | 30 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs | +| LinePragmas.cs:9:1:9:43 | #line ... | 2 | 1 | 5 | 32 | LinePragmasRef2.cs:0:0:0:0 | LinePragmasRef2.cs | +linespan_offset +| LinePragmas.cs:7:1:7:45 | #line ... | 5 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs | diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.ql b/csharp/ql/test/library-tests/csharp10/linePragmas.ql new file mode 100644 index 00000000000..41bf0a60d31 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/linePragmas.ql @@ -0,0 +1,13 @@ +import csharp + +query predicate linespan_directives( + SpanLineDirective directive, int startLine, int startColumn, int endLine, int endColumn, File file +) { + file = directive.getReferencedFile() and + directive.span(startLine, startColumn, endLine, endColumn) +} + +query predicate linespan_offset(SpanLineDirective directive, int offset, File file) { + file = directive.getReferencedFile() and + offset = directive.getOffset() +} diff --git a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected index c8f326c449c..1da3b58b9e3 100644 --- a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected +++ b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected @@ -1 +1 @@ -| RecordTypeSealedToString.cs:5:35:5:42 | ToString | +| RecordTypes.cs:5:35:5:42 | ToString | diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.expected b/csharp/ql/test/library-tests/csharp10/recordTypes.expected new file mode 100644 index 00000000000..786d42c8d71 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/recordTypes.expected @@ -0,0 +1,13 @@ +recordTypes +| RecordTypes.cs:3:1:6:2 | MyEntry | +| RecordTypes.cs:8:1:8:53 | MyClassRecord | +| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct | +| RecordTypes.cs:12:1:12:51 | MyRecordStruct1 | +| WithExpression.cs:9:1:9:47 | MyRecordStruct2 | +recordStructs +| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct | +| RecordTypes.cs:12:1:12:51 | MyRecordStruct1 | +| WithExpression.cs:9:1:9:47 | MyRecordStruct2 | +recordClass +| RecordTypes.cs:3:1:6:2 | MyEntry | +| RecordTypes.cs:8:1:8:53 | MyClassRecord | diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.ql b/csharp/ql/test/library-tests/csharp10/recordTypes.ql new file mode 100644 index 00000000000..1f96dab12da --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/recordTypes.ql @@ -0,0 +1,7 @@ +import csharp + +query predicate recordTypes(RecordType rt) { any() } + +query predicate recordStructs(RecordStruct rs) { any() } + +query predicate recordClass(RecordClass r) { any() } diff --git a/csharp/ql/test/library-tests/csharp10/structTypes.expected b/csharp/ql/test/library-tests/csharp10/structTypes.expected new file mode 100644 index 00000000000..dc46b426ea5 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/structTypes.expected @@ -0,0 +1,5 @@ +structAllDefaultConstructors +| StructTypes.cs:4:15:4:46 | MyStructParameterlessConstructor | StructTypes.cs:10:12:10:43 | MyStructParameterlessConstructor | +| StructTypes.cs:19:15:19:29 | MyDefaultStruct | StructTypes.cs:19:15:19:29 | MyDefaultStruct | +structFromSourceDefaultConstructors +| StructTypes.cs:4:15:4:46 | MyStructParameterlessConstructor | StructTypes.cs:10:12:10:43 | MyStructParameterlessConstructor | diff --git a/csharp/ql/test/library-tests/csharp10/structTypes.ql b/csharp/ql/test/library-tests/csharp10/structTypes.ql new file mode 100644 index 00000000000..1b4f95f1305 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/structTypes.ql @@ -0,0 +1,15 @@ +import csharp + +predicate structDefaultConstructors(Struct struct, Constructor c) { + struct.getAConstructor() = c and + struct.getFile().getBaseName() = "StructTypes.cs" and + c.hasNoParameters() +} + +query predicate structAllDefaultConstructors(Struct struct, Constructor c) { + structDefaultConstructors(struct, c) +} + +query predicate structFromSourceDefaultConstructors(Struct struct, Constructor c) { + structDefaultConstructors(struct, c) and c.fromSource() +} diff --git a/csharp/ql/test/library-tests/csharp10/withExpression.expected b/csharp/ql/test/library-tests/csharp10/withExpression.expected new file mode 100644 index 00000000000..b9a3ede0a69 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/withExpression.expected @@ -0,0 +1,3 @@ +| WithExpression.cs:16:18:16:34 | ... with { ... } | MyStruct | WithExpression.cs:16:18:16:19 | access to local variable s1 | WithExpression.cs:16:26:16:34 | { ..., ... } | +| WithExpression.cs:22:18:22:34 | ... with { ... } | MyRecordStruct2 | WithExpression.cs:22:18:22:19 | access to local variable r1 | WithExpression.cs:22:26:22:34 | { ..., ... } | +| WithExpression.cs:28:21:28:40 | ... with { ... } | <>__AnonType0 | WithExpression.cs:28:21:28:25 | access to local variable anon1 | WithExpression.cs:28:32:28:40 | { ..., ... } | diff --git a/csharp/ql/test/library-tests/csharp10/withExpression.ql b/csharp/ql/test/library-tests/csharp10/withExpression.ql new file mode 100644 index 00000000000..52475e7a005 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp10/withExpression.ql @@ -0,0 +1,7 @@ +import csharp + +query predicate withExpressions(WithExpr with, string type, Expr expr, ObjectInitializer init) { + type = with.getType().toStringWithTypes() and + expr = with.getExpr() and + init = with.getInitializer() +} diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index cb6414d9bb4..e346a782c4f 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -776,7 +776,7 @@ ParenthesizedPattern.cs: # 26| 0: [TypeMention] string # 26| 2: [IntLiteral] 5 Record.cs: -# 4| [Record] Person +# 4| [RecordClass] Person # 4| 11: [NEOperator] != #-----| 2: (Parameters) # 4| 0: [Parameter] left @@ -806,7 +806,7 @@ Record.cs: # 9| 1: [TupleExpr] (..., ...) # 9| 0: [ParameterAccess] access to parameter first # 9| 1: [ParameterAccess] access to parameter last -# 12| [Record] Teacher +# 12| [RecordClass] Teacher # 12| 12: [NEOperator] != #-----| 2: (Parameters) # 12| 0: [Parameter] left @@ -834,7 +834,7 @@ Record.cs: # 17| 4: [AssignExpr] ... = ... # 17| 0: [PropertyCall] access to property Subject # 17| 1: [ParameterAccess] access to parameter sub -# 20| [Record] Student +# 20| [RecordClass] Student # 20| 12: [NEOperator] != #-----| 2: (Parameters) # 20| 0: [Parameter] left @@ -862,7 +862,7 @@ Record.cs: # 24| 4: [AssignExpr] ... = ... # 24| 0: [PropertyCall] access to property Level # 24| 1: [ParameterAccess] access to parameter level -# 27| [Record] Person1 +# 27| [RecordClass] Person1 # 27| 12: [NEOperator] != #-----| 2: (Parameters) # 27| 0: [Parameter] left @@ -889,7 +889,7 @@ Record.cs: # 27| 4: [Setter] set_LastName #-----| 2: (Parameters) # 27| 0: [Parameter] value -# 29| [Record] Teacher1 +# 29| [RecordClass] Teacher1 # 29| 13: [NEOperator] != #-----| 2: (Parameters) # 29| 0: [Parameter] left @@ -913,7 +913,7 @@ Record.cs: # 29| 4: [Setter] set_Subject #-----| 2: (Parameters) # 29| 0: [Parameter] value -# 32| [Record] Student1 +# 32| [RecordClass] Student1 # 32| 13: [NEOperator] != #-----| 2: (Parameters) # 32| 0: [Parameter] left @@ -937,7 +937,7 @@ Record.cs: # 32| 4: [Setter] set_Level #-----| 2: (Parameters) # 32| 0: [Parameter] value -# 35| [Record] Pet +# 35| [RecordClass] Pet # 35| 12: [NEOperator] != #-----| 2: (Parameters) # 35| 0: [Parameter] left @@ -963,7 +963,7 @@ Record.cs: # 38| -1: [TypeAccess] access to type Console # 38| 0: [TypeMention] Console # 38| 0: [StringLiteral] "Shredding furniture" -# 41| [Record] Dog +# 41| [RecordClass] Dog # 41| 12: [NEOperator] != #-----| 2: (Parameters) # 41| 0: [Parameter] left @@ -1002,7 +1002,7 @@ Record.cs: # 50| 0: [MethodCall] call to method ToString # 50| -1: [LocalVariableAccess] access to local variable s # 50| 1: [StringLiteral] " is a dog" -# 54| [Record] R1 +# 54| [RecordClass] R1 # 54| 12: [NEOperator] != #-----| 2: (Parameters) # 54| 0: [Parameter] left @@ -1022,7 +1022,7 @@ Record.cs: # 54| 4: [Setter] set_A #-----| 2: (Parameters) # 54| 0: [Parameter] value -# 56| [Record] R2 +# 56| [RecordClass] R2 # 56| 13: [NEOperator] != #-----| 2: (Parameters) # 56| 0: [Parameter] left diff --git a/csharp/ql/test/library-tests/csharp9/record.ql b/csharp/ql/test/library-tests/csharp9/record.ql index 9a8da357d69..7fc45550365 100644 --- a/csharp/ql/test/library-tests/csharp9/record.ql +++ b/csharp/ql/test/library-tests/csharp9/record.ql @@ -1,6 +1,6 @@ import csharp -query predicate records(Record t, string i, RecordCloneMethod clone) { +query predicate records(RecordClass t, string i, RecordCloneMethod clone) { t.getABaseInterface().toStringWithTypes() = i and clone = t.getCloneMethod() and t.fromSource() @@ -10,7 +10,7 @@ private string getMemberName(Member m) { result = m.getDeclaringType().getQualifiedName() + "." + m.toStringWithTypes() } -query predicate members(Record t, string ms, string l) { +query predicate members(RecordClass t, string ms, string l) { t.fromSource() and exists(Member m | t.hasMember(m) | ms = getMemberName(m) and diff --git a/csharp/ql/test/library-tests/dataflow/fields/F.cs b/csharp/ql/test/library-tests/dataflow/fields/F.cs index 2e7cd9b6e2c..3754dff53ff 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/F.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/F.cs @@ -5,7 +5,7 @@ public class F static F Create(object o1, object o2) => new F() { Field1 = o1, Field2 = o2 }; - private void M() + private void M1() { var o = Source(1); var f = Create(o, null); @@ -25,6 +25,15 @@ public class F Sink(f.Field2); // $ hasValueFlow=4 } + private void M2() + { + var o = Source(2); + object @null = null; + var a = new { X = o, Y = @null }; + Sink(a.X); // $ hasValueFlow=2 + Sink(a.Y); // no flow + } + public static void Sink(object o) { } static T Source(object source) => throw null; diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected index 79c27103b1f..9d18b7ebad4 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected @@ -456,6 +456,14 @@ edges | F.cs:23:32:23:48 | call to method Source : Object | F.cs:23:21:23:50 | { ..., ... } [field Field2] : Object | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | F.cs:25:14:25:21 | access to field Field2 | +| F.cs:30:17:30:33 | call to method Source : Object | F.cs:32:27:32:27 | access to local variable o : Object | +| F.cs:30:17:30:33 | call to method Source : Object | F.cs:32:27:32:27 | access to local variable o : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | F.cs:33:14:33:14 | access to local variable a [property X] : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | F.cs:33:14:33:14 | access to local variable a [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | F.cs:32:17:32:40 | { ..., ... } [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | F.cs:32:17:32:40 | { ..., ... } [property X] : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | F.cs:33:14:33:16 | access to property X | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | F.cs:33:14:33:16 | access to property X | | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:9:23:9:23 | access to local variable e : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | G.cs:10:18:10:18 | access to local variable b [field Box1, field Elem] : Elem | @@ -776,28 +784,116 @@ edges | I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 | | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 | -| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object | -| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | -| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | -| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | -| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 | -| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 | -| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 | -| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 | -| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | -| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | -| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | -| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | -| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 | -| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 | -| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 | -| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 | +| J.cs:14:26:14:30 | field : Object | J.cs:14:66:14:70 | access to parameter field : Object | +| J.cs:14:26:14:30 | field : Object | J.cs:14:66:14:70 | access to parameter field : Object | +| J.cs:14:40:14:43 | prop : Object | J.cs:14:73:14:76 | access to parameter prop : Object | +| J.cs:14:40:14:43 | prop : Object | J.cs:14:73:14:76 | access to parameter prop : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | +| J.cs:21:17:21:33 | call to method Source : Object | J.cs:22:34:22:34 | access to local variable o : Object | +| J.cs:21:17:21:33 | call to method Source : Object | J.cs:22:34:22:34 | access to local variable o : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | J.cs:23:14:23:21 | access to property Prop1 | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | J.cs:23:14:23:21 | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | J.cs:27:14:27:21 | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | J.cs:27:14:27:21 | access to property Prop1 | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | J.cs:31:14:31:21 | access to property Prop1 | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | J.cs:31:14:31:21 | access to property Prop1 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | J.cs:32:14:32:21 | access to property Prop2 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | J.cs:32:14:32:21 | access to property Prop2 | +| J.cs:41:17:41:33 | call to method Source : Object | J.cs:42:35:42:35 | access to local variable o : Object | +| J.cs:41:17:41:33 | call to method Source : Object | J.cs:42:35:42:35 | access to local variable o : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | J.cs:43:14:43:21 | access to property Prop1 | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | J.cs:43:14:43:21 | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | J.cs:47:14:47:21 | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | J.cs:47:14:47:21 | access to property Prop1 | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | J.cs:51:14:51:21 | access to property Prop1 | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | J.cs:51:14:51:21 | access to property Prop1 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | J.cs:52:14:52:21 | access to property Prop2 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | J.cs:52:14:52:21 | access to property Prop2 | +| J.cs:61:17:61:33 | call to method Source : Object | J.cs:62:29:62:29 | access to local variable o : Object | +| J.cs:61:17:61:33 | call to method Source : Object | J.cs:62:29:62:29 | access to local variable o : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | J.cs:65:14:65:21 | access to field Field | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | J.cs:65:14:65:21 | access to field Field | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | J.cs:69:14:69:21 | access to field Field | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | J.cs:69:14:69:21 | access to field Field | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | J.cs:70:14:70:20 | access to property Prop | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | J.cs:70:14:70:20 | access to property Prop | +| J.cs:79:17:79:33 | call to method Source : Object | J.cs:80:35:80:35 | access to local variable o : Object | +| J.cs:79:17:79:33 | call to method Source : Object | J.cs:80:35:80:35 | access to local variable o : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | J.cs:84:14:84:20 | access to property Prop | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | J.cs:84:14:84:20 | access to property Prop | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | J.cs:87:14:87:21 | access to field Field | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | J.cs:87:14:87:21 | access to field Field | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | J.cs:88:14:88:20 | access to property Prop | +| J.cs:97:17:97:33 | call to method Source : Object | J.cs:99:28:99:28 | access to local variable o : Object | +| J.cs:97:17:97:33 | call to method Source : Object | J.cs:99:28:99:28 | access to local variable o : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | J.cs:99:18:99:41 | { ..., ... } [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | J.cs:99:18:99:41 | { ..., ... } [property X] : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | J.cs:102:14:102:17 | access to property X | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | J.cs:102:14:102:17 | access to property X | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | J.cs:106:14:106:17 | access to property X | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | J.cs:106:14:106:17 | access to property X | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | J.cs:107:14:107:17 | access to property Y | nodes | A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C | | A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C | @@ -1297,6 +1393,16 @@ nodes | F.cs:25:14:25:14 | access to local variable f [field Field2] : Object | semmle.label | access to local variable f [field Field2] : Object | | F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | | F.cs:25:14:25:21 | access to field Field2 | semmle.label | access to field Field2 | +| F.cs:30:17:30:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| F.cs:30:17:30:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| F.cs:32:17:32:40 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:32:27:32:27 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | semmle.label | access to local variable a [property X] : Object | +| F.cs:33:14:33:14 | access to local variable a [property X] : Object | semmle.label | access to local variable a [property X] : Object | +| F.cs:33:14:33:16 | access to property X | semmle.label | access to property X | +| F.cs:33:14:33:16 | access to property X | semmle.label | access to property X | | G.cs:7:18:7:32 | call to method Source : Elem | semmle.label | call to method Source : Elem | | G.cs:7:18:7:32 | call to method Source : Elem | semmle.label | call to method Source : Elem | | G.cs:9:9:9:9 | [post] access to local variable b [field Box1, field Elem] : Elem | semmle.label | [post] access to local variable b [field Box1, field Elem] : Elem | @@ -1637,32 +1743,136 @@ nodes | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object | | I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 | | I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 | -| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object | -| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object | -| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | -| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | -| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | -| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | -| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | -| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | -| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | -| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | -| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object | -| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | -| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | -| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 | -| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | -| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | -| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 | -| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object | +| J.cs:14:26:14:30 | field : Object | semmle.label | field : Object | +| J.cs:14:40:14:43 | prop : Object | semmle.label | prop : Object | +| J.cs:14:40:14:43 | prop : Object | semmle.label | prop : Object | +| J.cs:14:50:14:54 | [post] this access [field Field] : Object | semmle.label | [post] this access [field Field] : Object | +| J.cs:14:50:14:54 | [post] this access [field Field] : Object | semmle.label | [post] this access [field Field] : Object | +| J.cs:14:57:14:60 | [post] this access [property Prop] : Object | semmle.label | [post] this access [property Prop] : Object | +| J.cs:14:57:14:60 | [post] this access [property Prop] : Object | semmle.label | [post] this access [property Prop] : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | semmle.label | access to parameter field : Object | +| J.cs:14:66:14:70 | access to parameter field : Object | semmle.label | access to parameter field : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | semmle.label | access to parameter prop : Object | +| J.cs:14:73:14:76 | access to parameter prop : Object | semmle.label | access to parameter prop : Object | +| J.cs:21:17:21:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:21:17:21:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:18:22:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:22:34:22:34 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:23:14:23:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:23:14:23:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:23:14:23:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:27:14:27:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:27:14:27:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:27:14:27:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:30:18:30:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:30:36:30:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:30:36:30:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:31:14:31:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:31:14:31:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:31:14:31:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:32:14:32:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:32:14:32:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:32:14:32:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:41:17:41:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:41:17:41:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:18:42:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:42:35:42:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:43:14:43:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object | +| J.cs:43:14:43:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:43:14:43:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:47:14:47:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object | +| J.cs:47:14:47:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:47:14:47:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:50:18:50:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object | +| J.cs:50:36:50:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:50:36:50:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:51:14:51:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object | +| J.cs:51:14:51:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:51:14:51:21 | access to property Prop1 | semmle.label | access to property Prop1 | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:52:14:52:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object | +| J.cs:52:14:52:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:52:14:52:21 | access to property Prop2 | semmle.label | access to property Prop2 | +| J.cs:61:17:61:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:61:17:61:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | semmle.label | object creation of type Struct [field Field] : Object | +| J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | semmle.label | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | semmle.label | access to local variable s2 [field Field] : Object | +| J.cs:65:14:65:15 | access to local variable s2 [field Field] : Object | semmle.label | access to local variable s2 [field Field] : Object | +| J.cs:65:14:65:21 | access to field Field | semmle.label | access to field Field | +| J.cs:65:14:65:21 | access to field Field | semmle.label | access to field Field | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | semmle.label | ... with { ... } [property Prop] : Object | +| J.cs:68:18:68:53 | ... with { ... } [property Prop] : Object | semmle.label | ... with { ... } [property Prop] : Object | +| J.cs:68:35:68:51 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:68:35:68:51 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:69:14:69:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:69:14:69:21 | access to field Field | semmle.label | access to field Field | +| J.cs:69:14:69:21 | access to field Field | semmle.label | access to field Field | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:70:14:70:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:70:14:70:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:70:14:70:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:79:17:79:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:79:17:79:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | semmle.label | object creation of type Struct [property Prop] : Object | +| J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | semmle.label | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | semmle.label | access to local variable s2 [property Prop] : Object | +| J.cs:84:14:84:15 | access to local variable s2 [property Prop] : Object | semmle.label | access to local variable s2 [property Prop] : Object | +| J.cs:84:14:84:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:84:14:84:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | semmle.label | ... with { ... } [field Field] : Object | +| J.cs:86:18:86:54 | ... with { ... } [field Field] : Object | semmle.label | ... with { ... } [field Field] : Object | +| J.cs:86:36:86:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:86:36:86:52 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:87:14:87:15 | access to local variable s3 [field Field] : Object | semmle.label | access to local variable s3 [field Field] : Object | +| J.cs:87:14:87:21 | access to field Field | semmle.label | access to field Field | +| J.cs:87:14:87:21 | access to field Field | semmle.label | access to field Field | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:88:14:88:15 | access to local variable s3 [property Prop] : Object | semmle.label | access to local variable s3 [property Prop] : Object | +| J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:88:14:88:20 | access to property Prop | semmle.label | access to property Prop | +| J.cs:97:17:97:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:97:17:97:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| J.cs:99:18:99:41 | { ..., ... } [property X] : Object | semmle.label | { ..., ... } [property X] : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:99:28:99:28 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | semmle.label | access to local variable a2 [property X] : Object | +| J.cs:102:14:102:15 | access to local variable a2 [property X] : Object | semmle.label | access to local variable a2 [property X] : Object | +| J.cs:102:14:102:17 | access to property X | semmle.label | access to property X | +| J.cs:102:14:102:17 | access to property X | semmle.label | access to property X | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | semmle.label | ... with { ... } [property Y] : Object | +| J.cs:105:18:105:50 | ... with { ... } [property Y] : Object | semmle.label | ... with { ... } [property Y] : Object | +| J.cs:105:32:105:48 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:105:32:105:48 | call to method Source : Object | semmle.label | call to method Source : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | semmle.label | access to local variable a3 [property X] : Object | +| J.cs:106:14:106:15 | access to local variable a3 [property X] : Object | semmle.label | access to local variable a3 [property X] : Object | +| J.cs:106:14:106:17 | access to property X | semmle.label | access to property X | +| J.cs:106:14:106:17 | access to property X | semmle.label | access to property X | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | semmle.label | access to local variable a3 [property Y] : Object | +| J.cs:107:14:107:15 | access to local variable a3 [property Y] : Object | semmle.label | access to local variable a3 [property Y] : Object | +| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y | +| J.cs:107:14:107:17 | access to property Y | semmle.label | access to property Y | subpaths | A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C | | A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C | @@ -1762,6 +1972,10 @@ subpaths | H.cs:147:25:147:38 | call to method Source : A | H.cs:138:27:138:27 | o : A | H.cs:142:16:142:34 | access to field FieldB : A | H.cs:147:17:147:39 | call to method Through : A | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | | H.cs:164:22:164:22 | access to local variable o : Object | H.cs:153:32:153:32 | o : Object | H.cs:157:9:157:9 | [post] access to parameter a [field FieldA, field FieldB] : Object | H.cs:164:19:164:19 | [post] access to local variable a [field FieldA, field FieldB] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:62:29:62:29 | access to local variable o : Object | J.cs:14:26:14:30 | field : Object | J.cs:14:50:14:54 | [post] this access [field Field] : Object | J.cs:62:18:62:36 | object creation of type Struct [field Field] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | +| J.cs:80:35:80:35 | access to local variable o : Object | J.cs:14:40:14:43 | prop : Object | J.cs:14:57:14:60 | [post] this access [property Prop] : Object | J.cs:80:18:80:36 | object creation of type Struct [property Prop] : Object | #select | A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:28 | call to method Source : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:28 | call to method Source : C | call to method Source : C | | A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:29 | call to method Source : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:29 | call to method Source : C1 | call to method Source : C1 | @@ -1796,6 +2010,7 @@ subpaths | F.cs:17:14:17:21 | access to field Field2 | F.cs:15:26:15:42 | call to method Source : Object | F.cs:17:14:17:21 | access to field Field2 | $@ | F.cs:15:26:15:42 | call to method Source : Object | call to method Source : Object | | F.cs:20:14:20:21 | access to field Field1 | F.cs:19:32:19:48 | call to method Source : Object | F.cs:20:14:20:21 | access to field Field1 | $@ | F.cs:19:32:19:48 | call to method Source : Object | call to method Source : Object | | F.cs:25:14:25:21 | access to field Field2 | F.cs:23:32:23:48 | call to method Source : Object | F.cs:25:14:25:21 | access to field Field2 | $@ | F.cs:23:32:23:48 | call to method Source : Object | call to method Source : Object | +| F.cs:33:14:33:16 | access to property X | F.cs:30:17:30:33 | call to method Source : Object | F.cs:33:14:33:16 | access to property X | $@ | F.cs:30:17:30:33 | call to method Source : Object | call to method Source : Object | | G.cs:39:14:39:35 | call to method GetElem | G.cs:7:18:7:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:7:18:7:32 | call to method Source : Elem | call to method Source : Elem | | G.cs:39:14:39:35 | call to method GetElem | G.cs:15:18:15:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:15:18:15:32 | call to method Source : Elem | call to method Source : Elem | | G.cs:39:14:39:35 | call to method GetElem | G.cs:23:18:23:32 | call to method Source : Elem | G.cs:39:14:39:35 | call to method GetElem | $@ | G.cs:23:18:23:32 | call to method Source : Elem | call to method Source : Elem | @@ -1815,7 +2030,20 @@ subpaths | I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object | | I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object | | I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:29 | call to method Source : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:29 | call to method Source : Object | call to method Source : Object | -| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object | -| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object | -| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object | -| J.cs:23:14:23:21 | access to property Prop2 | J.cs:21:36:21:52 | call to method Source : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:21:36:21:52 | call to method Source : Object | call to method Source : Object | +| J.cs:23:14:23:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:23:14:23:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:27:14:27:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:27:14:27:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:31:14:31:21 | access to property Prop1 | J.cs:21:17:21:33 | call to method Source : Object | J.cs:31:14:31:21 | access to property Prop1 | $@ | J.cs:21:17:21:33 | call to method Source : Object | call to method Source : Object | +| J.cs:32:14:32:21 | access to property Prop2 | J.cs:30:36:30:52 | call to method Source : Object | J.cs:32:14:32:21 | access to property Prop2 | $@ | J.cs:30:36:30:52 | call to method Source : Object | call to method Source : Object | +| J.cs:43:14:43:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:43:14:43:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:47:14:47:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:47:14:47:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:51:14:51:21 | access to property Prop1 | J.cs:41:17:41:33 | call to method Source : Object | J.cs:51:14:51:21 | access to property Prop1 | $@ | J.cs:41:17:41:33 | call to method Source : Object | call to method Source : Object | +| J.cs:52:14:52:21 | access to property Prop2 | J.cs:50:36:50:52 | call to method Source : Object | J.cs:52:14:52:21 | access to property Prop2 | $@ | J.cs:50:36:50:52 | call to method Source : Object | call to method Source : Object | +| J.cs:65:14:65:21 | access to field Field | J.cs:61:17:61:33 | call to method Source : Object | J.cs:65:14:65:21 | access to field Field | $@ | J.cs:61:17:61:33 | call to method Source : Object | call to method Source : Object | +| J.cs:69:14:69:21 | access to field Field | J.cs:61:17:61:33 | call to method Source : Object | J.cs:69:14:69:21 | access to field Field | $@ | J.cs:61:17:61:33 | call to method Source : Object | call to method Source : Object | +| J.cs:70:14:70:20 | access to property Prop | J.cs:68:35:68:51 | call to method Source : Object | J.cs:70:14:70:20 | access to property Prop | $@ | J.cs:68:35:68:51 | call to method Source : Object | call to method Source : Object | +| J.cs:84:14:84:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:84:14:84:20 | access to property Prop | $@ | J.cs:79:17:79:33 | call to method Source : Object | call to method Source : Object | +| J.cs:87:14:87:21 | access to field Field | J.cs:86:36:86:52 | call to method Source : Object | J.cs:87:14:87:21 | access to field Field | $@ | J.cs:86:36:86:52 | call to method Source : Object | call to method Source : Object | +| J.cs:88:14:88:20 | access to property Prop | J.cs:79:17:79:33 | call to method Source : Object | J.cs:88:14:88:20 | access to property Prop | $@ | J.cs:79:17:79:33 | call to method Source : Object | call to method Source : Object | +| J.cs:102:14:102:17 | access to property X | J.cs:97:17:97:33 | call to method Source : Object | J.cs:102:14:102:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source : Object | call to method Source : Object | +| J.cs:106:14:106:17 | access to property X | J.cs:97:17:97:33 | call to method Source : Object | J.cs:106:14:106:17 | access to property X | $@ | J.cs:97:17:97:33 | call to method Source : Object | call to method Source : Object | +| J.cs:107:14:107:17 | access to property Y | J.cs:105:32:105:48 | call to method Source : Object | J.cs:107:14:107:17 | access to property Y | $@ | J.cs:105:32:105:48 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs index b53cdb2e97e..18a85890b91 100644 --- a/csharp/ql/test/library-tests/dataflow/fields/J.cs +++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs @@ -3,14 +3,23 @@ namespace System.Runtime.CompilerServices internal static class IsExternalInit { } } -public record Record(object Prop1, object Prop2) { } +public record class RecordClass(object Prop1, object Prop2) { } + +public record struct RecordStruct(object Prop1, object Prop2) { } + +public struct Struct +{ + public object Field; + public object Prop { get; init; } + public Struct(object field, object prop) => (Field, Prop) = (field, prop); +} public class J { private void M1() { var o = Source(1); - var r1 = new Record(o, null); + var r1 = new RecordClass(o, null); Sink(r1.Prop1); // $ hasValueFlow=1 Sink(r1.Prop2); // no flow @@ -27,6 +36,81 @@ public class J Sink(r4.Prop2); // no flow } + private void M2() + { + var o = Source(2); + var r1 = new RecordStruct(o, null); + Sink(r1.Prop1); // $ hasValueFlow=2 + Sink(r1.Prop2); // no flow + + var r2 = r1 with { }; + Sink(r2.Prop1); // $ hasValueFlow=2 + Sink(r2.Prop2); // no flow + + var r3 = r1 with { Prop2 = Source(3) }; + Sink(r3.Prop1); // $ hasValueFlow=2 + Sink(r3.Prop2); // $ hasValueFlow=3 + + var r4 = r1 with { Prop1 = null }; + Sink(r4.Prop1); // no flow + Sink(r4.Prop2); // no flow + } + + private void M3() + { + var o = Source(3); + var s1 = new Struct(o, null); + + var s2 = s1 with { }; + Sink(s2.Field); // $ hasValueFlow=3 + Sink(s2.Prop); // no flow + + var s3 = s1 with { Prop = Source(4) }; + Sink(s3.Field); // $ hasValueFlow=3 + Sink(s3.Prop); // $ hasValueFlow=4 + + var s4 = s1 with { Field = null }; + Sink(s4.Field); // no flow + Sink(s4.Prop); // no flow + } + + private void M4() + { + var o = Source(5); + var s1 = new Struct(null, o); + + var s2 = s1 with { }; + Sink(s2.Field); // $ no flow + Sink(s2.Prop); // $ hasValueFlow=5 + + var s3 = s1 with { Field = Source(6) }; + Sink(s3.Field); // $ hasValueFlow=6 + Sink(s3.Prop); // $ hasValueFlow=5 + + var s4 = s1 with { Prop = null }; + Sink(s4.Field); // no flow + Sink(s4.Prop); // no flow + } + + private void M5() + { + var o = Source(7); + object @null = null; + var a1 = new { X = o, Y = @null }; + + var a2 = a1 with { }; + Sink(a2.X); // $ hasValueFlow=7 + Sink(a2.Y); // no flow + + var a3 = a1 with { Y = Source(8) }; + Sink(a3.X); // $ hasValueFlow=7 + Sink(a3.Y); // $ hasValueFlow=8 + + var a4 = a1 with { X = @null }; + Sink(a4.X); // no flow + Sink(a4.Y); // no flow + } + public static void Sink(object o) { } static T Source(object source) => throw null; diff --git a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected index bfec8378220..6b509daa1bb 100644 --- a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected +++ b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected @@ -281,7 +281,7 @@ Tuples.cs: # 81| 2: [ExprStmt] ...; # 81| 0: [MethodCall] call to method Sink # 81| 0: [LocalVariableAccess] access to local variable q -# 85| 9: [Record] R1 +# 85| 9: [RecordClass] R1 # 85| 12: [NEOperator] != #-----| 2: (Parameters) # 85| 0: [Parameter] left diff --git a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs index 18d5e86dd24..cf3062f8af6 100644 --- a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs +++ b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs @@ -61,4 +61,8 @@ class LocalScopeVariableShadowsMember { public C4(int f) { } // GOOD } + + record class GoodRecordClass(object Prop1, object Prop2) { } // GOOD + + record struct GoodRecordStruct(object Prop1, object Prop2) { } // GOOD } diff --git a/csharp/ql/test/shared/FlowSummaries.qll b/csharp/ql/test/shared/FlowSummaries.qll index d8350f71b7f..6afa16a744a 100644 --- a/csharp/ql/test/shared/FlowSummaries.qll +++ b/csharp/ql/test/shared/FlowSummaries.qll @@ -38,7 +38,7 @@ abstract class IncludeSummarizedCallable extends RelevantSummarizedCallable { this.getDeclaringType().hasQualifiedName(namespace, type) and result = namespace + ";" + type + ";" + this.getCallableOverride() + ";" + this.getName() + ";" + "(" - + parameterQualifiedTypeNamesToString() + ")" + + this.parameterQualifiedTypeNamesToString() + ")" ) } } diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index de8566c32c6..a3e4c1b5504 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -266,14 +266,18 @@ up to create and analyze databases: available for database creation. This will list the languages supported by default in your CodeQL CLI package. - Run ``codeql resolve qlpacks`` to show which QL packs the CLI can find. This - will display the names of the QL packs included in the CodeQL repositories: - ``codeql-cpp``, ``codeql-csharp``, ``codeql-go``, - ``codeql-java``, ``codeql-javascript``, and ``codeql-python``. The CodeQL - repositories also contain 'upgrade' packs and 'legacy' packs. Upgrade packs - are used by the CLI when you want to upgrade a database so that it can be - analyzed with a newer version of the CodeQL toolchain than was used to create - it. Legacy packs ensure that custom queries and libraries created using older - products are compatible with your version of CodeQL. + will display the names of all the QL packs directly available to the CodeQL CLI. + This should include: + + - Query packs for each supported language, for example, ``codeql/{language}-queries``. + These packs contain the standard queries that will be run for each analysis. + - Library packs for each supported language, for example, ``codeql/{language}-all``. These + packs contain query libraries, such as control flow and data flow libraries, that + may be useful to query writers. + - Example packs for each supported language, for example, ``codeql/{language}-examples``. + These packs contain useful snippets of CodeQL that query writers may find useful. + - Legacy packs that ensure custom queries and libraries created using older products are + compatible with your version of CodeQL. .. _using-two-versions-of-the-codeql-cli: diff --git a/docs/codeql/writing-codeql-queries/river-crossing.ql b/docs/codeql/writing-codeql-queries/river-crossing.ql index 6b0e5cfe2a3..397ac7e39f8 100644 --- a/docs/codeql/writing-codeql-queries/river-crossing.ql +++ b/docs/codeql/writing-codeql-queries/river-crossing.ql @@ -95,7 +95,7 @@ class State extends string { exists(string pathSoFar, string visitedStatesSoFar, Cargo cargo | result = this.reachesVia(pathSoFar, visitedStatesSoFar).safeFerry(cargo) and // The resulting state has not yet been visited. - not exists(int i | i = visitedStatesSoFar.indexOf(result)) and + not exists(visitedStatesSoFar.indexOf(result)) and visitedStates = visitedStatesSoFar + "/" + result and path = pathSoFar + "\n Ferry " + cargo ) @@ -115,4 +115,3 @@ class GoalState extends State { from string path where any(InitialState i).reachesVia(path, _) = any(GoalState g) select path - diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 9576ed23eec..997d48c5010 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -1,111 +1,111 @@ -package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value -android.app,7,,84,,,,,,7,,,,,,,,,,,,,,,,,,13,71 -android.content,24,27,96,,,,,,16,,,,,,,,,8,,,,,,,27,,31,65 -android.database,59,,30,,,,,,,,,,,,,,,59,,,,,,,,,30, -android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,45,15 -android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,41,81 -android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,16,, -android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,3,,2,, -androidx.slice,,5,88,,,,,,,,,,,,,,,,,,,,,,5,,27,61 -cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,6, -com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,62,23 -com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,17 -com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,2,551 -com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,, -com.google.common.io,6,,73,,,,,,,,,,,,,,,,6,,,,,,,,72,1 -com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,, -com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,, -flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1 -groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,, -groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,, -jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,, -jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23 -jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,, -jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,, -jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,2,,,,,,,94,55 -java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -java.io,37,,31,,15,,,,,,,,,,,,,,,,22,,,,,,30,1 -java.lang,8,,56,,,,,,,,,,8,,,,,,,,,,,,,,45,11 -java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,3,7, -java.nio,15,,4,,13,,,,,,,,,,,,,,,,2,,,,,,4, -java.sql,7,,,,,,,,,,,,,,,,,7,,,,,,,,,, -java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,16,414 -javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,, -javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23 -javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,, -javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,, -javax.net.ssl,2,,,,,,,,,,,,,,,,2,,,,,,,,,,, -javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,, -javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,21,2, -javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,1,, -javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,, -javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,, -javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,2,,,,,,,94,55 -javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,1,,,,6, -javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,3,,,,,, -jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,10 -net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,5,,,,, -ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,, -org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,6, -org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783 -org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783 -org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,22, -org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,, -org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,, -org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,293,131 -org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,, -org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,, -org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,220,52 -org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,, -org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,1,,2,39, -org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,2, -org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,18,6 -org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,2,,3,62,8 -org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,6,,,,,,,,,, -org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,, -org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,4,4 -org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,, -org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,, -org.dom4j,20,,,,,,,,,,,,,,,,,,,,,20,,,,,, -org.hibernate,7,,,,,,,,,,,,,,,,,7,,,,,,,,,, -org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,, -org.jooq,1,,,,,,,,,,,,,,,,,1,,,,,,,,,, -org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,198,38 -org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,, -org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,, -org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,2,4 -org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,26 -org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13 -org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,3, -org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,60,10 -org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,10,,,,,,,,,, -org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,9,,,,,,,,,, -org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,, -org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,, -org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,6,, -org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,32 -org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,87,52 -org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,13, -org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,3,, -org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,8,, -org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,12,13, -org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,, -org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,138,25 -org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,1, -org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,3,, -play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,4,, -ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,48 -ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3, -ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35 -ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4, -ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10, -ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35 +package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value +android.app,16,,103,,,,,,7,,,,,,,,9,,,,,,,,,,,18,85 +android.content,24,27,96,,,,,,16,,,,,,,,,,8,,,,,,,27,,31,65 +android.database,59,,30,,,,,,,,,,,,,,,,59,,,,,,,,,30, +android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,45,15 +android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,,41,81 +android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,,16,, +android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,3,,2,, +androidx.slice,2,5,88,,,,,,,,,,,,,,2,,,,,,,,,5,,27,61 +cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6, +com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,,62,23 +com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,17 +com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,2,551 +com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,, +com.google.common.io,6,,73,,,,,,,,,,,,,,,,,6,,,,,,,,72,1 +com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,, +com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,, +flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1 +groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,, +groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,, +jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,, +jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23 +jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,, +jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,, +jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,2,,,,,,,94,55 +java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +java.io,37,,31,,15,,,,,,,,,,,,,,,,,22,,,,,,31, +java.lang,8,,58,,,,,,,,,,8,,,,,,,,,,,,,,,46,12 +java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,,3,7, +java.nio,15,,6,,13,,,,,,,,,,,,,,,,,2,,,,,,6, +java.sql,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,, +java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,,16,414 +javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,, +javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23 +javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,, +javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,, +javax.net.ssl,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,, +javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,, +javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,21,2, +javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,1,, +javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,, +javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,, +javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,2,,,,,,,94,55 +javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,1,,,,6, +javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,3,,,,,, +jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,10 +net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,5,,,,, +ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,, +org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6, +org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783 +org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783 +org.apache.commons.io,93,2,565,,78,,,,,,,,,,,15,,,,,,,,,,,2,551,14 +org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,, +org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,, +org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,293,131 +org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,, +org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,, +org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,220,52 +org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,, +org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,1,,2,39, +org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,2, +org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,18,6 +org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,,2,,3,62,8 +org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,,6,,,,,,,,,, +org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,, +org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,,4,4 +org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,, +org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,, +org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,20,,,,,, +org.hibernate,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,, +org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,, +org.jooq,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,, +org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,198,38 +org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,, +org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,, +org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,,2,4 +org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,26 +org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,13 +org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3, +org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,,60,10 +org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,10,,,,,,,,,, +org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,9,,,,,,,,,, +org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,, +org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,, +org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,, +org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,32 +org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,87,52 +org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13, +org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,,3,, +org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,8,, +org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,12,13, +org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,, +org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,138,25 +org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1, +org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,, +play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,4,, +ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,48 +ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3, +ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35 +ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4, +ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10, +ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35 diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index 013af21c2da..b49a31e2072 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -7,17 +7,17 @@ Java framework & library support :widths: auto Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission` - Android,``android.*``,45,392,99,,,3,67,,, + Android,``android.*``,45,411,108,,,3,67,,, `Apache Commons Collections `_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,, - `Apache Commons IO `_,``org.apache.commons.io``,,22,,,,,,,, + `Apache Commons IO `_,``org.apache.commons.io``,2,565,93,78,,,,,,15 `Apache Commons Lang `_,``org.apache.commons.lang3``,,424,,,,,,,, `Apache Commons Text `_,``org.apache.commons.text``,,272,,,,,,,, `Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25 `Google Guava `_,``com.google.common.*``,,728,35,,6,,,,, `JSON-java `_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,529,111,28,,,7,,,10 + Java Standard Library,``java.*``,3,533,111,28,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2 `Spring `_,``org.springframework.*``,29,472,91,,,,19,14,,29 - Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,919,,,,14,18,, - Totals,,180,5646,1315,28,6,10,107,33,1,66 + Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,921,,,,14,18,, + Totals,,182,6212,1419,106,6,10,107,33,1,81 diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index a4158696b3c..58b8954d1e2 100755 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -1750,7 +1750,7 @@ class TypeAccess extends Expr, Annotatable, @typeaccess { Expr getQualifier() { result.isNthChildOf(this, -1) } /** Holds if this type access has a qualifier. */ - predicate hasQualifier() { exists(Expr e | e = this.getQualifier()) } + predicate hasQualifier() { exists(this.getQualifier()) } /** Gets a type argument supplied to this type access. */ Expr getATypeArgument() { result.getIndex() >= 0 and result.getParent() = this } @@ -1762,7 +1762,7 @@ class TypeAccess extends Expr, Annotatable, @typeaccess { } /** Holds if this type access has a type argument. */ - predicate hasTypeArgument() { exists(Expr e | e = this.getATypeArgument()) } + predicate hasTypeArgument() { exists(this.getATypeArgument()) } /** Gets the compilation unit in which this type access occurs. */ override CompilationUnit getCompilationUnit() { result = Expr.super.getCompilationUnit() } diff --git a/java/ql/lib/semmle/code/java/Generics.qll b/java/ql/lib/semmle/code/java/Generics.qll index e1bf32d475b..95471437988 100755 --- a/java/ql/lib/semmle/code/java/Generics.qll +++ b/java/ql/lib/semmle/code/java/Generics.qll @@ -101,7 +101,7 @@ class GenericInterface extends GenericType, Interface { */ abstract class BoundedType extends RefType, @boundedtype { /** Holds if this type is bounded. */ - predicate hasTypeBound() { exists(TypeBound tb | tb = this.getATypeBound()) } + predicate hasTypeBound() { exists(this.getATypeBound()) } /** Gets a type bound for this type, if any. */ TypeBound getATypeBound() { result.getBoundedType() = this } diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index 082fb2ab295..31c81f46c0f 100755 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -636,7 +636,7 @@ class BreakStmt extends Stmt, @breakstmt { string getLabel() { namestrings(result, _, this) } /** Holds if this `break` statement has an explicit label. */ - predicate hasLabel() { exists(string s | s = this.getLabel()) } + predicate hasLabel() { exists(this.getLabel()) } override string pp() { if this.hasLabel() then result = "break " + this.getLabel() else result = "break" @@ -673,7 +673,7 @@ class ContinueStmt extends Stmt, @continuestmt { string getLabel() { namestrings(result, _, this) } /** Holds if this `continue` statement has an explicit label. */ - predicate hasLabel() { exists(string s | s = this.getLabel()) } + predicate hasLabel() { exists(this.getLabel()) } override string pp() { if this.hasLabel() then result = "continue " + this.getLabel() else result = "continue" diff --git a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll index 8e9d90769f3..055671f7592 100644 --- a/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/UnreachableBlocks.qll @@ -212,7 +212,7 @@ class UnreachableBasicBlock extends BasicBlock { not exists(Callable c | c.getBody() = this) and not this instanceof Callable and not exists(Annotation a | a.getAChildExpr*() = this) and - not exists(AssertStmt a | a = this.(Expr).getEnclosingStmt()) and + not this.(Expr).getEnclosingStmt() instanceof AssertStmt and not this instanceof CatchClause or // Switch statements with a constant comparison expression may have unreachable cases. diff --git a/java/ql/lib/semmle/code/java/controlflow/internal/GuardsLogic.qll b/java/ql/lib/semmle/code/java/controlflow/internal/GuardsLogic.qll index 7c4d49c90c7..269a626c785 100644 --- a/java/ql/lib/semmle/code/java/controlflow/internal/GuardsLogic.qll +++ b/java/ql/lib/semmle/code/java/controlflow/internal/GuardsLogic.qll @@ -23,19 +23,23 @@ predicate implies_v1(Guard g1, boolean b1, Guard g2, boolean b2) { or g1.(OrBitwiseExpr).getAnOperand() = g2 and b1 = false and b2 = false or + g1.(AssignAndExpr).getSource() = g2 and b1 = true and b2 = true + or + g1.(AssignOrExpr).getSource() = g2 and b1 = false and b2 = false + or g1.(AndLogicalExpr).getAnOperand() = g2 and b1 = true and b2 = true or g1.(OrLogicalExpr).getAnOperand() = g2 and b1 = false and b2 = false or g1.(LogNotExpr).getExpr() = g2 and b1 = b2.booleanNot() and - (b1 = true or b1 = false) + b1 = [true, false] or exists(EqualityTest eqtest, boolean polarity, BooleanLiteral boollit | eqtest = g1 and eqtest.hasOperands(g2, boollit) and eqtest.polarity() = polarity and - (b1 = true or b1 = false) and + b1 = [true, false] and b2 = b1.booleanXor(polarity).booleanXor(boollit.getBooleanValue()) ) or @@ -56,16 +60,20 @@ predicate implies_v1(Guard g1, boolean b1, Guard g2, boolean b2) { exists(MethodAccess check | check = g1 | conditionCheck(check, _) and g2 = check.getArgument(0) and - (b1 = true or b1 = false) and + b1 = [true, false] and b2 = b1 ) or exists(BaseSsaUpdate vbool | + vbool.getDefiningExpr().(VariableAssign).getSource() = g2 or + vbool.getDefiningExpr().(AssignOp) = g2 + | vbool.getAUse() = g1 and - vbool.getDefiningExpr().(VariableAssign).getSource() = g2 and - (b1 = true or b1 = false) and + b1 = [true, false] and b2 = b1 ) + or + g1.(AssignExpr).getSource() = g2 and b2 = b1 and b1 = [true, false] } /** @@ -79,9 +87,11 @@ predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) { implies_v1(g1, b1, g2, b2) or exists(SsaExplicitUpdate vbool | + vbool.getDefiningExpr().(VariableAssign).getSource() = g2 or + vbool.getDefiningExpr().(AssignOp) = g2 + | vbool.getAUse() = g1 and - vbool.getDefiningExpr().(VariableAssign).getSource() = g2 and - (b1 = true or b1 = false) and + b1 = [true, false] and b2 = b1 ) or diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll index d8d02f995a6..2d49800545a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll @@ -17,6 +17,7 @@ import semmle.code.java.frameworks.android.WebView import semmle.code.java.frameworks.JaxWS import semmle.code.java.frameworks.javase.WebSocket import semmle.code.java.frameworks.android.Android +import semmle.code.java.frameworks.android.OnActivityResultSource import semmle.code.java.frameworks.android.Intent import semmle.code.java.frameworks.play.Play import semmle.code.java.frameworks.spring.SpringWeb @@ -109,7 +110,7 @@ private class MessageBodyReaderParameterSource extends RemoteFlowSource { } private class PlayParameterSource extends RemoteFlowSource { - PlayParameterSource() { exists(PlayActionMethodQueryParameter p | p = this.asParameter()) } + PlayParameterSource() { this.asParameter() instanceof PlayActionMethodQueryParameter } override string getSourceType() { result = "Play Query Parameters" } } @@ -264,3 +265,13 @@ class ExportedAndroidContentProviderInput extends RemoteFlowSource, AndroidConte override string getSourceType() { result = "Exported Android content provider source" } } + +/** + * The data Intent parameter in the `onActivityResult` method in an Activity or Fragment that + * calls `startActivityForResult` with an implicit Intent. + */ +class OnActivityResultIntentSource extends OnActivityResultIncomingIntent, RemoteFlowSource { + OnActivityResultIntentSource() { this.isRemoteSource() } + + override string getSourceType() { result = "Android onActivityResult incoming Intent" } +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll new file mode 100644 index 00000000000..b66c1aa3c2f --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll @@ -0,0 +1,19 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses (for internal use only). + * + * This copy of the library is exclusively for use by `OnActivityResultSource.qll` and + * related libraries. Configurations computed using this instance of the library + * are in scope whenever `java.qll` is imported, and are used to compute among + * other things `RemoteFlowSource`s. + */ + +import java + +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses (for internal use only). + */ +module DataFlowForOnActivityResult { + import semmle.code.java.dataflow.internal.DataFlowImplForOnActivityResult +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll new file mode 100644 index 00000000000..fb806910898 --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -0,0 +1,5187 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Configuration` class. This file exists in several identical + * copies, allowing queries to use multiple `Configuration` classes that depend + * on each other without introducing mutual recursion among those configurations. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node source, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** Holds if data flow through nodes guarded by `guard` is prohibited. */ + predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * Holds if the additional flow step from `node1` to `node2` must be taken + * into account in the analysis. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if the additional flow step from `node1` to `node2` must be taken + * into account in the analysis. This step is only applicable in `state1` and + * updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, Content c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + */ + FlowFeature getAFeature() { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { flowsTo(source, sink, _, _, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + int explorationLimit() { none() } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * This predicate is disabled (has no results) by default. Override + * `explorationLimit()` with a suitable number to enable this predicate. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node, this) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * This predicate is disabled (has no results) by default. Override + * `explorationLimit()` with a suitable number to enable this predicate. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink, this) and + dist = node.getSinkDistance() + } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] + } + +private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() + or + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") + } + + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } + + pragma[nomagic] + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) + } + + pragma[inline] + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) + } + + pragma[nomagic] + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } +} + +private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + + predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) } +} + +private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } +} + +private predicate inBarrier(NodeEx node, Configuration config) { + exists(Node n | + node.asNode() = n and + config.isBarrierIn(n) + | + config.isSource(n) or config.isSource(n, _) + ) +} + +private predicate outBarrier(NodeEx node, Configuration config) { + exists(Node n | + node.asNode() = n and + config.isBarrierOut(n) + | + config.isSink(n) or config.isSink(n, _) + ) +} + +pragma[nomagic] +private predicate fullBarrier(NodeEx node, Configuration config) { + exists(Node n | node.asNode() = n | + config.isBarrier(n) + or + config.isBarrierIn(n) and + not config.isSource(n) and + not config.isSource(n, _) + or + config.isBarrierOut(n) and + not config.isSink(n) and + not config.isSink(n, _) + or + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + ) +} + +pragma[nomagic] +private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { + exists(Node n | + node.asNode() = n and + config.isBarrier(n, state) + ) +} + +pragma[nomagic] +private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { + ( + config.isSource(node.asNode()) and state instanceof FlowStateEmpty + or + config.isSource(node.asNode(), state) + ) and + not fullBarrier(node, config) and + not stateBarrier(node, state, config) +} + +pragma[nomagic] +private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { + ( + config.isSink(node.asNode()) and state instanceof FlowStateEmpty + or + config.isSink(node.asNode(), state) + ) and + not fullBarrier(node, config) and + not stateBarrier(node, state, config) +} + +/** Provides the relevant barriers for a step from `node1` to `node2`. */ +pragma[inline] +private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { + not outBarrier(node1, config) and + not inBarrier(node2, config) and + not fullBarrier(node1, config) and + not fullBarrier(node2, config) +} + +/** + * Holds if data can flow in one local step from `node1` to `node2`. + */ +private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(n1, n2) and + stepFilter(node1, node2, config) + ) + or + exists(Node n | + config.allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1, config) + ) +} + +/** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ +private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + config.isAdditionalFlowStep(n1, n2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2, config) + ) + or + exists(Node n | + config.allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2, config) + ) +} + +private predicate additionalLocalStateStep( + NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config +) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + config.isAdditionalFlowStep(n1, s1, n2, s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2, config) and + not stateBarrier(node1, s1, config) and + not stateBarrier(node2, s2, config) + ) +} + +/** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ +private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(n1, n2) and + stepFilter(node1, node2, config) and + not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) +} + +/** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ +private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + config.isAdditionalFlowStep(n1, n2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2, config) and + not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) +} + +private predicate additionalJumpStateStep( + NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config +) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + config.isAdditionalFlowStep(n1, s1, n2, s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2, config) and + not stateBarrier(node1, s1, config) and + not stateBarrier(node2, s2, config) and + not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) +} + +private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { + read(node1.asNode(), c, node2.asNode()) and + stepFilter(node1, node2, config) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + config.allowImplicitRead(n, c) + ) +} + +private predicate store( + NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config +) { + store(node1.asNode(), tc, node2.asNode(), contentType) and + read(_, tc.getContent(), _, config) and + stepFilter(node1, node2, config) +} + +pragma[nomagic] +private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) +} + +pragma[nomagic] +private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) +} + +/** + * Holds if field flow should be used for the given configuration. + */ +private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } + +private predicate hasSourceCallCtx(Configuration config) { + exists(FlowFeature feature | feature = config.getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) +} + +private predicate hasSinkCallCtx(Configuration config) { + exists(FlowFeature feature | feature = config.getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) +} + +private module Stage1 { + class ApApprox = Unit; + + class Ap = Unit; + + class ApOption = Unit; + + class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source in the configuration `config`. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { + sourceNode(node, _, config) and + if hasSourceCallCtx(config) then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc, config) | + localFlowStep(mid, node, config) or + additionalLocalFlowStep(mid, node, config) or + additionalLocalStateStep(mid, _, node, _, config) + ) + or + exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | + jumpStep(mid, node, config) or + additionalJumpStep(mid, node, config) or + additionalJumpStateStep(mid, _, node, _, config) + ) + or + // store + exists(NodeEx mid | + useFieldFlow(config) and + fwdFlow(mid, cc, config) and + store(mid, _, node, _, config) + ) + or + // read + exists(Content c | + fwdFlowRead(c, node, cc, config) and + fwdFlowConsCand(c, config) + ) + or + // flow into a callable + exists(NodeEx arg | + fwdFlow(arg, _, config) and + viableParamArgEx(_, node, arg) and + cc = true and + not fullBarrier(node, config) + ) + or + // flow out of a callable + exists(DataFlowCall call | + fwdFlowOut(call, node, false, config) and + cc = false + or + fwdFlowOutFromArg(call, node, config) and + fwdFlowIsEntered(call, cc, config) + ) + } + + private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } + + pragma[nomagic] + private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) { + exists(NodeEx mid | + fwdFlow(mid, cc, config) and + read(mid, c, node, config) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Content c, Configuration config) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node, config) and + useFieldFlow(config) and + fwdFlow(mid, _, config) and + store(mid, tc, node, _, config) and + c = tc.getContent() + ) + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { + exists(RetNodeEx ret | + fwdFlow(ret, cc, config) and + ret.getReturnPosition() = pos + ) + } + + pragma[nomagic] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc, config) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out, config) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { + fwdFlowOut(call, out, true, config) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { + exists(ArgNodeEx arg | + fwdFlow(arg, cc, config) and + viableParamArgEx(call, _, arg) + ) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2, config) or + additionalJumpStateStep(node1, state1, _, state2, config) + | + fwdFlow(node1, config) + ) + } + + private predicate fwdFlowState(FlowState state, Configuration config) { + sourceNode(_, state, config) + or + exists(FlowState state0 | + fwdFlowState(state0, config) and + stateStepFwd(state0, state, config) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink in the + * configuration `config`. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { + revFlow0(node, toReturn, config) and + fwdFlow(node, config) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { + exists(FlowState state | + fwdFlow(node, pragma[only_bind_into](config)) and + sinkNode(node, state, config) and + fwdFlowState(state, pragma[only_bind_into](config)) and + if hasSinkCallCtx(config) then toReturn = true else toReturn = false + ) + or + exists(NodeEx mid | revFlow(mid, toReturn, config) | + localFlowStep(node, mid, config) or + additionalLocalFlowStep(node, mid, config) or + additionalLocalStateStep(node, _, mid, _, config) + ) + or + exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | + jumpStep(node, mid, config) or + additionalJumpStep(node, mid, config) or + additionalJumpStateStep(node, _, mid, _, config) + ) + or + // store + exists(Content c | + revFlowStore(c, node, toReturn, config) and + revFlowConsCand(c, config) + ) + or + // read + exists(NodeEx mid, Content c | + read(node, c, mid, config) and + fwdFlowConsCand(c, pragma[only_bind_into](config)) and + revFlow(mid, toReturn, pragma[only_bind_into](config)) + ) + or + // flow into a callable + exists(DataFlowCall call | + revFlowIn(call, node, false, config) and + toReturn = false + or + revFlowInToReturn(call, node, config) and + revFlowIsReturned(call, toReturn, config) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(pos, config) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + } + + /** + * Holds if `c` is the target of a read in the flow covered by `revFlow`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Content c, Configuration config) { + exists(NodeEx mid, NodeEx node | + fwdFlow(node, pragma[only_bind_into](config)) and + read(node, c, mid, config) and + fwdFlowConsCand(c, pragma[only_bind_into](config)) and + revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) + ) + } + + pragma[nomagic] + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn, pragma[only_bind_into](config)) and + fwdFlowConsCand(c, pragma[only_bind_into](config)) and + store(node, tc, mid, _, config) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + private predicate revFlowIsReadAndStored(Content c, Configuration conf) { + revFlowConsCand(c, conf) and + revFlowStore(c, _, _, conf) + } + + pragma[nomagic] + predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config + ) { + fwdFlowReturnPosition(pos, _, config) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, NodeEx out | + revFlow(out, _, config) and + viableReturnPosOutNodeCandFwd1(call, pos, out, config) + ) + } + + pragma[nomagic] + predicate viableParamArgNodeCandFwd1( + DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config + ) { + viableParamArgEx(call, p, arg) and + fwdFlow(arg, config) + } + + pragma[nomagic] + private predicate revFlowIn( + DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config + ) { + exists(ParamNodeEx p | + revFlow(p, toReturn, config) and + viableParamArgNodeCandFwd1(call, p, arg, config) + ) + } + + pragma[nomagic] + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { + revFlowIn(call, arg, true, config) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { + exists(NodeEx out | + revFlow(out, toReturn, config) and + fwdFlowOutFromArg(call, out, config) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2, config) or + additionalJumpStateStep(node1, state1, node2, state2, config) + | + revFlow(node1, _, pragma[only_bind_into](config)) and + revFlow(node2, _, pragma[only_bind_into](config)) and + fwdFlowState(state1, pragma[only_bind_into](config)) and + fwdFlowState(state2, pragma[only_bind_into](config)) + ) + } + + predicate revFlowState(FlowState state, Configuration config) { + exists(NodeEx node | + sinkNode(node, state, config) and + revFlow(node, _, pragma[only_bind_into](config)) and + fwdFlowState(state, pragma[only_bind_into](config)) + ) + or + exists(FlowState state0 | + revFlowState(state0, config) and + stateStepRev(state, state0, config) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, + Configuration config + ) { + exists(Content c | + revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and + revFlow(node2, pragma[only_bind_into](config)) and + store(node1, tc, node2, contentType, config) and + c = tc.getContent() and + exists(ap1) + ) + } + + pragma[nomagic] + predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { + revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and + revFlow(n2, pragma[only_bind_into](config)) and + read(n1, c, n2, pragma[only_bind_into](config)) + } + + pragma[nomagic] + predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } + + bindingset[node, state, config] + predicate revFlow( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node, Configuration config) { + revFlow(node, true, config) and + fwdFlow(node, true, config) and + not inBarrier(node, config) and + not outBarrier(node, config) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand( + DataFlowCallable callable, ReturnKindExt kind, Configuration config + ) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret, config) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { + exists(ReturnKindExt kind | + throughFlowNodeCand(p, config) and + returnFlowCallableNodeCand(c, kind, config) and + p.getEnclosingCallable() = c and + exists(ap) and + // we don't expect a parameter to return stored in itself, unless explicitly allowed + ( + not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition() + or + p.allowParameterReturnInSelf() + ) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn, config) and + revFlowInToReturn(call, arg, config) and + revFlowIsReturned(call, toReturn, config) + ) + } + + predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, config)) and + fields = count(Content f0 | fwdFlowConsCand(f0, config)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state, config)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, config)) and + fields = count(Content f0 | revFlowConsCand(f0, config)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state, config)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) + } + /* End: Stage 1 logic. */ +} + +pragma[noinline] +private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { + Stage1::revFlow(node2, config) and + localFlowStep(node1, node2, config) +} + +pragma[noinline] +private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { + Stage1::revFlow(node2, config) and + additionalLocalFlowStep(node1, node2, config) +} + +pragma[nomagic] +private predicate viableReturnPosOutNodeCand1( + DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config +) { + Stage1::revFlow(out, config) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) +} + +/** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ +pragma[nomagic] +private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, NodeEx out, Configuration config +) { + viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and + Stage1::revFlow(ret, config) and + not outBarrier(ret, config) and + not inBarrier(out, config) +} + +pragma[nomagic] +private predicate viableParamArgNodeCand1( + DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config +) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and + Stage1::revFlow(arg, config) +} + +/** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ +pragma[nomagic] +private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config +) { + viableParamArgNodeCand1(call, p, arg, config) and + Stage1::revFlow(p, config) and + not outBarrier(arg, config) and + not inBarrier(p, config) +} + +/** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ +private int branch(NodeEx n1, Configuration conf) { + result = + strictcount(NodeEx n | + flowOutOfCallNodeCand1(_, n1, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) + ) +} + +/** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ +private int join(NodeEx n2, Configuration conf) { + result = + strictcount(NodeEx n | + flowOutOfCallNodeCand1(_, n, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) + ) +} + +/** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ +pragma[nomagic] +private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config +) { + flowOutOfCallNodeCand1(call, ret, out, config) and + exists(int b, int j | + b = branch(ret, config) and + j = join(out, config) and + if b.minimum(j) <= config.fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) +} + +/** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ +pragma[nomagic] +private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config +) { + flowIntoCallNodeCand1(call, arg, p, config) and + exists(int b, int j | + b = branch(arg, config) and + j = join(p, config) and + if b.minimum(j) <= config.fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) +} + +private module Stage2 { + module PrevStage = Stage1; + + class ApApprox = PrevStage::Ap; + + class Ap = boolean; + + class ApNil extends Ap { + ApNil() { this = false } + } + + bindingset[result, ap] + private ApApprox getApprox(Ap ap) { any() } + + private ApNil getApNil(NodeEx node) { PrevStage::revFlow(node, _) and exists(result) } + + bindingset[tc, tail] + private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + pragma[inline] + private Content getHeadContent(Ap ap) { exists(result) and ap = true } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + class Cc = CallContext; + + class CcCall = CallContextCall; + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + private class LocalCc = Unit; + + bindingset[call, c, outercc] + private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + + bindingset[call, c, innercc] + private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + } + + bindingset[node, cc, config] + private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() } + + bindingset[node1, state1, config] + bindingset[node2, state2, config] + private predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, Configuration config, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2, config) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2, config) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2, config) + ) and + exists(ap) and + exists(lcc) + } + + private predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + private predicate flowIntoCall = flowIntoCallNodeCand1/5; + + bindingset[node, state, ap, config] + private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { + PrevStage::revFlowState(state, config) and + exists(ap) and + not stateBarrier(node, state, config) + } + + bindingset[ap, contentType] + private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + + /* Begin: Stage 2 logic. */ + bindingset[node, state, config] + private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) { + PrevStage::revFlow(node, state, _, _, apa, config) + } + + bindingset[result, apa] + private ApApprox unbindApa(ApApprox apa) { + pragma[only_bind_out](apa) = pragma[only_bind_out](result) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + Configuration config + ) { + flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _, + pragma[only_bind_into](config)) and + ccc.matchesCall(call) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source in the + * configuration `config`. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `argAp` records the access path of that + * argument. + */ + pragma[nomagic] + predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) { + fwdFlow0(node, state, cc, argAp, ap, config) and + flowCand(node, state, unbindApa(getApprox(ap)), config) and + filter(node, state, ap, config) + } + + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + sourceNode(node, state, config) and + (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + ap = getApNil(node) + or + exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc | + fwdFlow(mid, state0, cc, argAp, ap0, config) and + localCc = getLocalCc(mid, cc, config) + | + localStep(mid, state0, node, state, true, _, config, localCc) and + ap = ap0 + or + localStep(mid, state0, node, state, false, ap, config, localCc) and + ap0 instanceof ApNil + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + jumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStateStep(mid, state0, node, state, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and + ap = apCons(tc, ap0) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and + fwdFlowConsCand(ap0, c, ap, config) + ) + or + // flow into a callable + exists(ApApprox apa | + fwdFlowIn(_, node, state, _, cc, _, ap, config) and + apa = getApprox(ap) and + if PrevStage::parameterMayFlowThrough(node, _, apa, config) + then argAp = apSome(ap) + else argAp = apNone() + ) + or + // flow out of a callable + fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config) + or + exists(DataFlowCall call, Ap argAp0 | + fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and + fwdFlowIsEntered(call, cc, argAp, argAp0, config) + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + exists(DataFlowType contentType | + fwdFlow(node1, state, cc, argAp, ap1, config) and + PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, config) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + fwdFlow(node1, state, cc, argAp, ap, config) and + PrevStage::readStepCand(node1, c, node2, config) and + getHeadContent(ap) = c + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp, + Ap ap, Configuration config + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, argAp, ap, config) and + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutNotFromArg( + NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config + ) { + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, argAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + inner = ret.getEnclosingCallable() and + ccOut = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg( + DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc | + fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and + flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p | + fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and + PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config) + ) + } + + pragma[nomagic] + private predicate storeStepFwd( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config + ) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config) + } + + private predicate readStepFwd( + NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config + ) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and + fwdFlowConsCand(ap1, c, ap2, config) + } + + pragma[nomagic] + private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) { + exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap, + pragma[only_bind_into](config)) and + fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and + fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc), + pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0), + pragma[only_bind_into](config)) + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config + ) { + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and + callMayFlowThroughFwd(call, pragma[only_bind_into](config)) + } + + pragma[nomagic] + private predicate returnNodeMayFlowThrough( + RetNodeEx ret, FlowState state, Ap ap, Configuration config + ) { + fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink in the configuration `config`. + * + * The Boolean `toReturn` records whether the node must be returned from the + * enclosing callable in order to reach a sink, and if so, `returnAp` records + * the access path of the returned value. + */ + pragma[nomagic] + predicate revFlow( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow0(node, state, toReturn, returnAp, ap, config) and + fwdFlow(node, state, _, _, ap, config) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + fwdFlow(node, state, _, _, ap, config) and + sinkNode(node, state, config) and + (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, ap, config) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStep(node, mid, config) and + revFlow(mid, state, _, _, ap, config) and + toReturn = false and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStep(node, mid, config) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStateStep(node, state, mid, state0, config) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, + pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and + revFlowConsCand(ap0, c, ap, config) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, toReturn, returnAp, ap0, config) and + readStepFwd(node, ap, _, mid, ap0, config) + ) + or + // flow into a callable + revFlowInNotToReturn(node, state, returnAp, ap, config) and + toReturn = false + or + exists(DataFlowCall call, Ap returnAp0 | + revFlowInToReturn(call, node, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + or + // flow out of a callable + revFlowOut(_, node, state, _, _, ap, config) and + toReturn = true and + if returnNodeMayFlowThrough(node, state, ap, config) + then returnAp = apSome(ap) + else returnAp = apNone() + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + boolean toReturn, ApOption returnAp, Configuration config + ) { + revFlow(mid, state, toReturn, returnAp, ap0, config) and + storeStepFwd(node, ap, tc, mid, ap0, config) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail, config) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0, config) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, + Configuration config + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, toReturn, returnAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInNotToReturn( + ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, false, returnAp, ap, config) and + flowIntoCall(_, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInToReturn( + DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, true, apSome(returnAp), ap, config) and + flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and + fwdFlow(ret, state, ccc, apSome(_), ap, config) and + ccc.matchesCall(call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, + Configuration config + ) { + exists(Ap ap2, Content c | + store(node1, tc, node2, contentType, config) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and + revFlowConsCand(ap2, c, ap1, config) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and + readStepFwd(node1, ap1, c, node2, ap2, config) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, + pragma[only_bind_into](config)) + ) + } + + predicate revFlow(NodeEx node, FlowState state, Configuration config) { + revFlow(node, state, _, _, _, config) + } + + pragma[nomagic] + predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow(node, state, toReturn, returnAp, ap, config) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { + storeStepFwd(_, ap, tc, _, _, config) + } + + predicate consCand(TypedContent tc, Ap ap, Configuration config) { + storeStepCand(_, ap, tc, _, _, config) + } + + pragma[noinline] + private predicate parameterFlow( + ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config + ) { + revFlow(p, _, true, apSome(ap0), ap, config) and + c = p.getEnclosingCallable() + } + + predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { + exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos | + parameterFlow(p, ap, ap0, c, config) and + c = ret.getEnclosingCallable() and + revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_), + pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and + fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and + kind = ret.getKind() and + p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed + ( + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() + ) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { + exists( + Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap + | + revFlow(arg, state, toReturn, returnAp, ap, config) and + revFlowInToReturn(call, arg, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + } + + predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, argAp, ap, config) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | consCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and + states = count(FlowState state | revFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap | + revFlow(n, state, b, retAp, ap, config) + ) + } + /* End: Stage 2 logic. */ +} + +pragma[nomagic] +private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, NodeEx node2, boolean allowsFieldFlow, Configuration config +) { + flowOutOfCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and + Stage2::revFlow(node2, pragma[only_bind_into](config)) and + Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) +} + +pragma[nomagic] +private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, + Configuration config +) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and + Stage2::revFlow(node2, pragma[only_bind_into](config)) and + Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) +} + +private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) + } + } + + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { + Stage2::revFlow(node, state, config) and + ( + sourceNode(node, state, config) or + jumpStep(_, node, config) or + additionalJumpStep(_, node, config) or + additionalJumpStateStep(_, _, node, state, config) or + node instanceof ParamNodeEx or + node.asNode() instanceof OutNodeExt or + store(_, _, node, _, config) or + read(_, _, node, config) or + node instanceof FlowCheckNode + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { + exists(NodeEx next | Stage2::revFlow(next, state, config) | + jumpStep(node, next, config) or + additionalJumpStep(node, next, config) or + flowIntoCallNodeCand1(_, node, next, config) or + flowOutOfCallNodeCand1(_, node, next, config) or + store(node, _, next, _, config) or + read(node, _, next, config) + ) + or + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | + additionalJumpStateStep(node, state, next, s, config) + ) + or + Stage2::revFlow(node, state, config) and + node instanceof FlowCheckNode + or + sinkNode(node, state, config) + } + + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config + ) { + additionalLocalFlowStepNodeCand1(node1, node2, config) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), _, _, false, + pragma[only_bind_into](config)) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), _, _, false, + pragma[only_bind_into](config)) + or + additionalLocalStateStep(node1, state1, node2, state2, config) and + Stage2::revFlow(node1, state1, _, _, false, pragma[only_bind_into](config)) and + Stage2::revFlowAlias(node2, state2, _, _, false, pragma[only_bind_into](config)) + } + + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, Configuration config, LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and + ( + localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and + ( + localFlowStepNodeCand1(node1, node2, config) and + state1 = state2 and + preservesValue = true and + t = node1.getDataFlowType() // irrelevant dummy value + or + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and + Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t, + pragma[only_bind_into](config), cc) and + localFlowStepNodeCand1(mid, node2, config) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config)) + ) + or + exists(NodeEx mid, FlowState st | + localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and + additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() and + Stage2::revFlow(node2, state2, pragma[only_bind_into](config)) + ) + ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + AccessPathFrontNil apf, Configuration config, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config, + callContext) and + localFlowExit(node2, state2, config) + } +} + +private import LocalFlowBigStep + +private module Stage3 { + module PrevStage = Stage2; + + class ApApprox = PrevStage::Ap; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + private ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + pragma[noinline] + private Content getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + class Cc = boolean; + + class CcCall extends Cc { + CcCall() { this = true } + + /** Holds if this call context may be `call`. */ + predicate matchesCall(DataFlowCall call) { any() } + } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } + + private class LocalCc = Unit; + + bindingset[call, c, outercc] + private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + + bindingset[node, cc, config] + private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() } + + private predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, Configuration config, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap, config, _) and exists(lcc) + } + + private predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + private predicate flowIntoCall = flowIntoCallNodeCand2/5; + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap, config] + private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { + exists(state) and + exists(config) and + not clear(node, ap) and + if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any() + } + + bindingset[ap, contentType] + private predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + + /* Begin: Stage 3 logic. */ + bindingset[node, state, config] + private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) { + PrevStage::revFlow(node, state, _, _, apa, config) + } + + bindingset[result, apa] + private ApApprox unbindApa(ApApprox apa) { + pragma[only_bind_out](apa) = pragma[only_bind_out](result) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + Configuration config + ) { + flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _, + pragma[only_bind_into](config)) and + ccc.matchesCall(call) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source in the + * configuration `config`. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `argAp` records the access path of that + * argument. + */ + pragma[nomagic] + predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) { + fwdFlow0(node, state, cc, argAp, ap, config) and + flowCand(node, state, unbindApa(getApprox(ap)), config) and + filter(node, state, ap, config) + } + + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + sourceNode(node, state, config) and + (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + ap = getApNil(node) + or + exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc | + fwdFlow(mid, state0, cc, argAp, ap0, config) and + localCc = getLocalCc(mid, cc, config) + | + localStep(mid, state0, node, state, true, _, config, localCc) and + ap = ap0 + or + localStep(mid, state0, node, state, false, ap, config, localCc) and + ap0 instanceof ApNil + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + jumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStateStep(mid, state0, node, state, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and + ap = apCons(tc, ap0) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and + fwdFlowConsCand(ap0, c, ap, config) + ) + or + // flow into a callable + exists(ApApprox apa | + fwdFlowIn(_, node, state, _, cc, _, ap, config) and + apa = getApprox(ap) and + if PrevStage::parameterMayFlowThrough(node, _, apa, config) + then argAp = apSome(ap) + else argAp = apNone() + ) + or + // flow out of a callable + fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config) + or + exists(DataFlowCall call, Ap argAp0 | + fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and + fwdFlowIsEntered(call, cc, argAp, argAp0, config) + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + exists(DataFlowType contentType | + fwdFlow(node1, state, cc, argAp, ap1, config) and + PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, config) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + fwdFlow(node1, state, cc, argAp, ap, config) and + PrevStage::readStepCand(node1, c, node2, config) and + getHeadContent(ap) = c + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp, + Ap ap, Configuration config + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, argAp, ap, config) and + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutNotFromArg( + NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config + ) { + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, argAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + inner = ret.getEnclosingCallable() and + ccOut = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg( + DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc | + fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and + flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p | + fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and + PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config) + ) + } + + pragma[nomagic] + private predicate storeStepFwd( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config + ) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config) + } + + private predicate readStepFwd( + NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config + ) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and + fwdFlowConsCand(ap1, c, ap2, config) + } + + pragma[nomagic] + private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) { + exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap, + pragma[only_bind_into](config)) and + fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and + fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc), + pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0), + pragma[only_bind_into](config)) + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config + ) { + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and + callMayFlowThroughFwd(call, pragma[only_bind_into](config)) + } + + pragma[nomagic] + private predicate returnNodeMayFlowThrough( + RetNodeEx ret, FlowState state, Ap ap, Configuration config + ) { + fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink in the configuration `config`. + * + * The Boolean `toReturn` records whether the node must be returned from the + * enclosing callable in order to reach a sink, and if so, `returnAp` records + * the access path of the returned value. + */ + pragma[nomagic] + predicate revFlow( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow0(node, state, toReturn, returnAp, ap, config) and + fwdFlow(node, state, _, _, ap, config) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + fwdFlow(node, state, _, _, ap, config) and + sinkNode(node, state, config) and + (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, ap, config) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStep(node, mid, config) and + revFlow(mid, state, _, _, ap, config) and + toReturn = false and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStep(node, mid, config) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStateStep(node, state, mid, state0, config) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, + pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and + revFlowConsCand(ap0, c, ap, config) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, toReturn, returnAp, ap0, config) and + readStepFwd(node, ap, _, mid, ap0, config) + ) + or + // flow into a callable + revFlowInNotToReturn(node, state, returnAp, ap, config) and + toReturn = false + or + exists(DataFlowCall call, Ap returnAp0 | + revFlowInToReturn(call, node, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + or + // flow out of a callable + revFlowOut(_, node, state, _, _, ap, config) and + toReturn = true and + if returnNodeMayFlowThrough(node, state, ap, config) + then returnAp = apSome(ap) + else returnAp = apNone() + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + boolean toReturn, ApOption returnAp, Configuration config + ) { + revFlow(mid, state, toReturn, returnAp, ap0, config) and + storeStepFwd(node, ap, tc, mid, ap0, config) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail, config) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0, config) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, + Configuration config + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, toReturn, returnAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInNotToReturn( + ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, false, returnAp, ap, config) and + flowIntoCall(_, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInToReturn( + DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, true, apSome(returnAp), ap, config) and + flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and + fwdFlow(ret, state, ccc, apSome(_), ap, config) and + ccc.matchesCall(call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, + Configuration config + ) { + exists(Ap ap2, Content c | + store(node1, tc, node2, contentType, config) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and + revFlowConsCand(ap2, c, ap1, config) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and + readStepFwd(node1, ap1, c, node2, ap2, config) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, + pragma[only_bind_into](config)) + ) + } + + predicate revFlow(NodeEx node, FlowState state, Configuration config) { + revFlow(node, state, _, _, _, config) + } + + pragma[nomagic] + predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow(node, state, toReturn, returnAp, ap, config) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { + storeStepFwd(_, ap, tc, _, _, config) + } + + predicate consCand(TypedContent tc, Ap ap, Configuration config) { + storeStepCand(_, ap, tc, _, _, config) + } + + pragma[noinline] + private predicate parameterFlow( + ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config + ) { + revFlow(p, _, true, apSome(ap0), ap, config) and + c = p.getEnclosingCallable() + } + + predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { + exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos | + parameterFlow(p, ap, ap0, c, config) and + c = ret.getEnclosingCallable() and + revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_), + pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and + fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and + kind = ret.getKind() and + p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed + ( + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() + ) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { + exists( + Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap + | + revFlow(arg, state, toReturn, returnAp, ap, config) and + revFlowInToReturn(call, arg, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + } + + predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, argAp, ap, config) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | consCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and + states = count(FlowState state | revFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap | + revFlow(n, state, b, retAp, ap, config) + ) + } + /* End: Stage 3 logic. */ +} + +/** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ +private predicate flowCandSummaryCtx( + NodeEx node, FlowState state, AccessPathFront argApf, Configuration config +) { + exists(AccessPathFront apf | + Stage3::revFlow(node, state, true, _, apf, config) and + Stage3::fwdFlow(node, state, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config) + ) +} + +/** + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. + */ +private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage3::consCand(tc, apf, config)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage3::revFlow(n, state, _, _, any(AccessPathFrontHead apf | apf.getHead() = tc), config) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() + ) +} + +private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage3::consCand(tc, TFrontNil(t), _) and + not expensiveLen2unfolding(tc, _) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage3::consCand(tc1, TFrontHead(tc2), _) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1, _) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc, _) + } + +/** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ +abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); +} + +private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; + + AccessPathApproxNil() { this = TNil(t) } + + override string toString() { result = concat(": " + ppReprType(t)) } + + override TypedContent getHead() { none() } + + override int len() { result = 0 } + + override DataFlowType getType() { result = t } + + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } +} + +abstract private class AccessPathApproxCons extends AccessPathApprox { } + +private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; + + AccessPathApproxConsNil() { this = TConsNil(tc, t) } + + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } + + override TypedContent getHead() { result = tc } + + override int len() { result = 1 } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } +} + +private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; + + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } + + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc1 } + + override int len() { result = len } + + override DataFlowType getType() { result = tc1.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc1) } + + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + } +} + +private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage3::consCand(tc, TFrontHead(tc2), _) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage3::consCand(tc, TFrontNil(t), _) and + result = TNil(t) + ) + ) + } +} + +/** Gets the access path obtained by popping `tc` from `ap`, if any. */ +private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + +/** Gets the access path obtained by pushing `tc` onto `ap`. */ +private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + +private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) + +private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } +} + +private module Stage4 { + module PrevStage = Stage3; + + class ApApprox = PrevStage::Ap; + + class Ap = AccessPathApprox; + + class ApNil = AccessPathApproxNil; + + private ApApprox getApprox(Ap ap) { result = ap.getFront() } + + private ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + pragma[noinline] + private Content getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + class Cc = CallContext; + + class CcCall = CallContextCall; + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + private class LocalCc = LocalCallContext; + + bindingset[call, c, outercc] + private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + } + + bindingset[call, c, innercc] + private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + } + + bindingset[node, cc, config] + private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { + localFlowEntry(node, _, config) and + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + private predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, Configuration config, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getFront(), config, lcc) + } + + pragma[nomagic] + private predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, NodeEx node2, boolean allowsFieldFlow, Configuration config + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _, _, _, + pragma[only_bind_into](config)) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, _, _, + pragma[only_bind_into](config)) + ) + } + + pragma[nomagic] + private predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, + Configuration config + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _, _, _, + pragma[only_bind_into](config)) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, _, _, + pragma[only_bind_into](config)) + ) + } + + bindingset[node, state, ap, config] + private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + + /* Begin: Stage 4 logic. */ + bindingset[node, state, config] + private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) { + PrevStage::revFlow(node, state, _, _, apa, config) + } + + bindingset[result, apa] + private ApApprox unbindApa(ApApprox apa) { + pragma[only_bind_out](apa) = pragma[only_bind_out](result) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + Configuration config + ) { + flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and + PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _, + pragma[only_bind_into](config)) and + ccc.matchesCall(call) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source in the + * configuration `config`. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `argAp` records the access path of that + * argument. + */ + pragma[nomagic] + predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) { + fwdFlow0(node, state, cc, argAp, ap, config) and + flowCand(node, state, unbindApa(getApprox(ap)), config) and + filter(node, state, ap, config) + } + + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + sourceNode(node, state, config) and + (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + ap = getApNil(node) + or + exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc | + fwdFlow(mid, state0, cc, argAp, ap0, config) and + localCc = getLocalCc(mid, cc, config) + | + localStep(mid, state0, node, state, true, _, config, localCc) and + ap = ap0 + or + localStep(mid, state0, node, state, false, ap, config, localCc) and + ap0 instanceof ApNil + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + jumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStep(mid, node, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and + additionalJumpStateStep(mid, state0, node, state, config) and + cc = ccNone() and + argAp = apNone() and + ap = getApNil(node) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and + ap = apCons(tc, ap0) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and + fwdFlowConsCand(ap0, c, ap, config) + ) + or + // flow into a callable + exists(ApApprox apa | + fwdFlowIn(_, node, state, _, cc, _, ap, config) and + apa = getApprox(ap) and + if PrevStage::parameterMayFlowThrough(node, _, apa, config) + then argAp = apSome(ap) + else argAp = apNone() + ) + or + // flow out of a callable + fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config) + or + exists(DataFlowCall call, Ap argAp0 | + fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and + fwdFlowIsEntered(call, cc, argAp, argAp0, config) + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + exists(DataFlowType contentType | + fwdFlow(node1, state, cc, argAp, ap1, config) and + PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, config) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp, + Configuration config + ) { + fwdFlow(node1, state, cc, argAp, ap, config) and + PrevStage::readStepCand(node1, c, node2, config) and + getHeadContent(ap) = c + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp, + Ap ap, Configuration config + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, argAp, ap, config) and + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutNotFromArg( + NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config + ) { + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, argAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + inner = ret.getEnclosingCallable() and + ccOut = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg( + DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc | + fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and + flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p | + fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and + PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config) + ) + } + + pragma[nomagic] + private predicate storeStepFwd( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config + ) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config) + } + + private predicate readStepFwd( + NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config + ) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and + fwdFlowConsCand(ap1, c, ap2, config) + } + + pragma[nomagic] + private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) { + exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap, + pragma[only_bind_into](config)) and + fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and + fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc), + pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0), + pragma[only_bind_into](config)) + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config + ) { + flowIntoCall(call, arg, p, allowsFieldFlow, config) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and + PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and + callMayFlowThroughFwd(call, pragma[only_bind_into](config)) + } + + pragma[nomagic] + private predicate returnNodeMayFlowThrough( + RetNodeEx ret, FlowState state, Ap ap, Configuration config + ) { + fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink in the configuration `config`. + * + * The Boolean `toReturn` records whether the node must be returned from the + * enclosing callable in order to reach a sink, and if so, `returnAp` records + * the access path of the returned value. + */ + pragma[nomagic] + predicate revFlow( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow0(node, state, toReturn, returnAp, ap, config) and + fwdFlow(node, state, _, _, ap, config) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + fwdFlow(node, state, _, _, ap, config) and + sinkNode(node, state, config) and + (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, ap, config) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and + revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStep(node, mid, config) and + revFlow(mid, state, _, _, ap, config) and + toReturn = false and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStep(node, mid, config) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and + additionalJumpStateStep(node, state, mid, state0, config) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, + pragma[only_bind_into](config)) and + toReturn = false and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and + revFlowConsCand(ap0, c, ap, config) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, toReturn, returnAp, ap0, config) and + readStepFwd(node, ap, _, mid, ap0, config) + ) + or + // flow into a callable + revFlowInNotToReturn(node, state, returnAp, ap, config) and + toReturn = false + or + exists(DataFlowCall call, Ap returnAp0 | + revFlowInToReturn(call, node, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + or + // flow out of a callable + revFlowOut(_, node, state, _, _, ap, config) and + toReturn = true and + if returnNodeMayFlowThrough(node, state, ap, config) + then returnAp = apSome(ap) + else returnAp = apNone() + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + boolean toReturn, ApOption returnAp, Configuration config + ) { + revFlow(mid, state, toReturn, returnAp, ap0, config) and + storeStepFwd(node, ap, tc, mid, ap0, config) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail, config) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0, config) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, + Configuration config + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, toReturn, returnAp, ap, config) and + flowOutOfCall(call, ret, out, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInNotToReturn( + ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, false, returnAp, ap, config) and + flowIntoCall(_, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowInToReturn( + DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config + ) { + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, true, apSome(returnAp), ap, config) and + flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and + fwdFlow(ret, state, ccc, apSome(_), ap, config) and + ccc.matchesCall(call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, + Configuration config + ) { + exists(Ap ap2, Content c | + store(node1, tc, node2, contentType, config) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and + revFlowConsCand(ap2, c, ap1, config) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and + readStepFwd(node1, ap1, c, node2, ap2, config) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, + pragma[only_bind_into](config)) + ) + } + + predicate revFlow(NodeEx node, FlowState state, Configuration config) { + revFlow(node, state, _, _, _, config) + } + + pragma[nomagic] + predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + predicate revFlowAlias( + NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config + ) { + revFlow(node, state, toReturn, returnAp, ap, config) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { + storeStepFwd(_, ap, tc, _, _, config) + } + + predicate consCand(TypedContent tc, Ap ap, Configuration config) { + storeStepCand(_, ap, tc, _, _, config) + } + + pragma[noinline] + private predicate parameterFlow( + ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config + ) { + revFlow(p, _, true, apSome(ap0), ap, config) and + c = p.getEnclosingCallable() + } + + predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) { + exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos | + parameterFlow(p, ap, ap0, c, config) and + c = ret.getEnclosingCallable() and + revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_), + pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and + fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and + kind = ret.getKind() and + p.getPosition() = pos and + // we don't expect a parameter to return stored in itself, unless explicitly allowed + ( + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + p.allowParameterReturnInSelf() + ) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { + exists( + Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap + | + revFlow(arg, state, toReturn, returnAp, ap, config) and + revFlowInToReturn(call, arg, state, returnAp0, ap, config) and + revFlowIsReturned(call, toReturn, returnAp, returnAp0, config) + ) + } + + predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, argAp, ap, config) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and + fields = count(TypedContent f0 | consCand(f0, _, config)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and + states = count(FlowState state | revFlow(_, state, _, _, _, config)) and + tuples = + count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap | + revFlow(n, state, b, retAp, ap, config) + ) + } + /* End: Stage 4 logic. */ +} + +bindingset[conf, result] +private Configuration unbindConf(Configuration conf) { + exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) +} + +private predicate nodeMayUseSummary( + NodeEx n, FlowState state, AccessPathApprox apa, Configuration config +) { + exists(DataFlowCallable c, AccessPathApprox apa0 | + Stage4::parameterMayFlowThrough(_, c, apa, _) and + Stage4::revFlow(n, state, true, _, apa0, config) and + Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and + n.getEnclosingCallable() = c + ) +} + +private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + exists(Configuration config | + Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), config) and + Stage4::revFlow(p, state, _, _, _, config) + ) + } + +/** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ +abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); +} + +/** A summary context from which no flow summary can be generated. */ +private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } +} + +/** A summary context from which a flow summary can be generated. */ +private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; + + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } + + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } + + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +/** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ +private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage4::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), + config) + ) + ) +} + +private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { + result = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, _, _, apa, config) or nodeMayUseSummary(n, state, apa, config) + ) +} + +/** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ +private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = count1to2unfold(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + apLimit < aps and + tupleLimit < (aps - 1) * nodes + ) +} + +private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { + exists(TypedContent head | + apa.pop(head) = result and + Stage4::consCand(head, result, config) + ) +} + +/** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ +private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { + if apa.getHead().forceHighPrecision() + then unfold = true + else + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa, config) and + nodes = countNodesUsingAccessPath(apa, config) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) +} + +/** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ +private int countAps(AccessPathApprox apa, Configuration config) { + evalUnfold(apa, false, config) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) + or + evalUnfold(apa, false, config) and + result = count1to2unfold(apa, config) and + not expensiveLen1to2unfolding(apa, config) + or + evalUnfold(apa, true, config) and + result = countPotentialAps(apa, config) +} + +/** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ +language[monotonicAggregates] +private int countPotentialAps(AccessPathApprox apa, Configuration config) { + apa instanceof AccessPathApproxNil and result = 1 + or + result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) +} + +private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false, _) and + head = apa.getHead() and + tail.getApprox() = getATail(apa, _) + ) + } or + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false, _) and + not expensiveLen1to2unfolding(apa, _) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa, _).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false, _) and + expensiveLen1to2unfolding(apa, _) and + apa.len() = len and + head = apa.getHead() + ) + } + +private newtype TPathNode = + TPathNodeMid( + NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config + ) { + // A PathNode is introduced by a source ... + Stage4::revFlow(node, state, config) and + sourceNode(node, state, config) and + ( + if hasSourceCallCtx(config) + then cc instanceof CallContextSomeCall + else cc instanceof CallContextAny + ) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + exists(PathNodeMid mid | + pathStep(mid, node, state, cc, sc, ap) and + pragma[only_bind_into](config) = mid.getConfiguration() and + Stage4::revFlow(node, state, _, _, ap.getApprox(), pragma[only_bind_into](config)) + ) + } or + TPathNodeSink(NodeEx node, FlowState state, Configuration config) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() and + config = sink.getConfiguration() + ) + } + +/** + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ +abstract private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ + abstract string toString(); + + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() + } + + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } +} + +private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } +} + +private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false + ) + } + + override string toString() { + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) + } +} + +private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage4::consCand(head1, result.getApprox(), _) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } +} + +private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; + + AccessPathCons1() { this = TAccessPathCons1(head, len) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { + Stage4::consCand(head, result.getApprox(), _) and result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } + + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } +} + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source are generated. + */ +class PathNode extends TPathNode { + /** Gets a textual representation of this element. */ + string toString() { none() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { none() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + none() + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + FlowState getState() { none() } + + /** Gets the associated configuration. */ + Configuration getConfiguration() { none() } + + private PathNode getASuccessorIfHidden() { + this.(PathNodeImpl).isHidden() and + result = this.(PathNodeImpl).getASuccessorImpl() + } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { + result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and + not this.(PathNodeImpl).isHidden() and + not result.(PathNodeImpl).isHidden() + } + + /** Holds if this node is a source. */ + predicate isSource() { none() } +} + +abstract private class PathNodeImpl extends PathNode { + abstract PathNode getASuccessorImpl(); + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } + + override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + override string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +/** Holds if `n` can reach a sink. */ +private predicate directReach(PathNode n) { + n instanceof PathNodeSink or directReach(n.getASuccessor()) +} + +/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ +private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } + +/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ +private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) } + +private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * Provides the query predicates needed to include a graph in a path-problem query. + */ +module PathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + reach(n) and key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) and + reach(arg) and + reach(par) and + reach(ret) and + reach(out) + } +} + +/** + * An intermediate flow graph node. This is a triple consisting of a `Node`, + * a `CallContext`, and a `Configuration`. + */ +private class PathNodeMid extends PathNodeImpl, TPathNodeMid { + NodeEx node; + FlowState state; + CallContext cc; + SummaryCtx sc; + AccessPath ap; + Configuration config; + + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } + + override NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + SummaryCtx getSummaryCtx() { result = sc } + + AccessPath getAp() { result = ap } + + override Configuration getConfiguration() { result = config } + + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) and + result.getConfiguration() = unbindConf(this.getConfiguration()) + } + + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state, config) and + ( + if hasSourceCallCtx(config) + then cc instanceof CallContextSomeCall + else cc instanceof CallContextAny + ) and + sc instanceof SummaryCtxNone and + ap instanceof AccessPathNil + } + + predicate isAtSink() { + sinkNode(node, state, config) and + ap instanceof AccessPathNil and + if hasSinkCallCtx(config) + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state and + result.getConfiguration() = unbindConf(config) + } +} + +/** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ +private class PathNodeSink extends PathNodeImpl, TPathNodeSink { + NodeEx node; + FlowState state; + Configuration config; + + PathNodeSink() { this = TPathNodeSink(node, state, config) } + + override NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + override Configuration getConfiguration() { result = config } + + override PathNode getASuccessorImpl() { none() } + + override predicate isSource() { sourceNode(node, state, config) } +} + +private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + Configuration conf, LocalCallContext localCC +) { + midnode = mid.getNodeEx() and + state = mid.getState() and + conf = mid.getConfiguration() and + cc = mid.getCallContext() and + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() +} + +/** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ +pragma[nomagic] +private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap +) { + exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) + ) + or + exists( + AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC + | + pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.getFront(), conf, localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() +} + +pragma[nomagic] +private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc +) { + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage4::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and + state = mid.getState() and + cc = mid.getCallContext() +} + +pragma[nomagic] +private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc +) { + ap0 = mid.getAp() and + Stage4::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and + state = mid.getState() and + cc = mid.getCallContext() +} + +private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, + Configuration config +) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and + apa = mid.getAp().getApprox() and + config = mid.getConfiguration() +} + +pragma[nomagic] +private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa, Configuration config +) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + pathOutOfCallable0(mid, pos, state, innercc, apa, config) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) +} + +pragma[noinline] +private NodeEx getAnOutNodeFlow( + ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config +) { + result.asNode() = kind.getAnOutNode(call) and + Stage4::revFlow(result, _, _, _, apa, config) +} + +/** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ +pragma[noinline] +private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | + pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) + ) +} + +/** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ +pragma[noinline] +private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa, Configuration config +) { + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, config, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and + parameterMatch(ppos, apos) + ) +} + +pragma[nomagic] +private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config +) { + exists(ParamNodeEx p | + Stage4::revFlow(p, _, _, _, apa, config) and + p.isParameterOf(callable, pos) + ) +} + +pragma[nomagic] +private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config +) { + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa), pragma[only_bind_into](config)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), + pragma[only_bind_into](config)) + ) +} + +/** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ +pragma[nomagic] +private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call, Configuration config +) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + p.isParameterOf(callable, pos) and + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) +} + +/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ +pragma[nomagic] +private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa, Configuration config +) { + exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos | + pathNode(mid, ret, state, cc, sc, ap, config, _) and + kind = ret.getKind() and + apa = ap.getApprox() and + pos = sc.getParameterPos() and + // we don't expect a parameter to return stored in itself, unless explicitly allowed + ( + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + sc.getParamNode().allowParameterReturnInSelf() + ) + ) +} + +pragma[nomagic] +private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa, Configuration config +) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) + ) +} + +/** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ +pragma[noinline] +private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap +) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and + out = getAnOutNodeFlow(kind, call, apa, config) + ) +} + +private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + exists(Configuration config | + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _, unbindConf(config)) and + not arg.isHidden() + ) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + pragma[nomagic] + private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _, _) or + store(n1, _, n2, _, _) or + read(n1, _, n2, _) + ) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getASuccessor() = par and + pragma[only_bind_into](arg).getASuccessor() = out0 and + subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and + not ret.isHidden() and + par.getNodeEx() = p and + out0.getNodeEx() = o and + out0.getState() = sout and + out0.getAp() = apout and + (out = out0 or out = out0.projectToSink()) + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNode n) { + exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNode mid | + retReach(mid) and + n.getASuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } +} + +/** + * Holds if data can flow (inter-procedurally) from `source` to `sink`. + * + * Will only have results if `configuration` has non-empty sources and + * sinks. + */ +private predicate flowsTo( + PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration +) { + flowsource.isSource() and + flowsource.getConfiguration() = configuration and + flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink +} + +/** + * Holds if data can flow (inter-procedurally) from `source` to `sink`. + * + * Will only have results if `configuration` has non-empty sources and + * sinks. + */ +predicate flowsTo(Node source, Node sink, Configuration configuration) { + flowsTo(_, _, source, sink, configuration) +} + +private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples +) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNode pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn | reach(pn)) +} + +/** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ +predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples, + Configuration config +) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples, config) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples, config) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples, config) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples, config) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples, config) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples, config) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples, config) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples, config) + or + stage = "5 Fwd" and n = 50 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and n = 55 and finalStats(false, nodes, fields, conscand, states, tuples) +} + +private module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { + exists(NodeEx node1, NodeEx node2 | + jumpStep(node1, node2, config) + or + additionalJumpStep(node1, node2, config) + or + additionalJumpStateStep(node1, _, node2, _, config) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { + exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | + interestingCallableSrc(mid, config) and callableStep(mid, c, config) + ) + } + + private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { + exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | + interestingCallableSink(mid, config) and callableStep(c, mid, config) + ) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c, Configuration config) { + interestingCallableSrc(c, config) or + interestingCallableSink(c, config) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | + callableStep(c1, c2, config) and + ce1 = TCallable(c1, pragma[only_bind_into](config)) and + ce2 = TCallable(c2, pragma[only_bind_into](config)) + ) + or + exists(Node n, Configuration config | + ce1 = TCallableSrc() and + (config.isSource(n) or config.isSource(n, _)) and + ce2 = TCallable(getNodeEnclosingCallable(n), config) + ) + or + exists(Node n, Configuration config | + ce2 = TCallableSink() and + (config.isSink(n) or config.isSink(n, _)) and + ce1 = TCallable(getNodeEnclosingCallable(n), config) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c, Configuration config) { + result = distSrcExt(TCallable(c, config)) - 1 + } + + private int distSink(DataFlowCallable c, Configuration config) { + result = distSinkExt(TCallable(c, config)) - 1 + } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state, _) or + sinkNode(_, state, _) or + additionalLocalStateStep(_, state, _, _, _) or + additionalLocalStateStep(_, _, _, state, _) or + additionalJumpStateStep(_, state, _, _, _) or + additionalJumpStateStep(_, _, _, state, _) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + ) { + sourceNode(node, state, config) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(config.explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and + distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap, Configuration config + ) { + sinkNode(node, state, config) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(config.explorationLimit()) + or + exists(PartialPathNodeRev mid | + revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and + not clearsContentCached(node.asNode(), ap.getHead()) and + not fullBarrier(node, config) and + not stateBarrier(node, state, config) and + distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + ) + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + ) { + exists(PartialPathNodeFwd mid | + partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and + not fullBarrier(node, config) and + not stateBarrier(node, state, config) and + not clearsContentCached(node.asNode(), ap.getHead().getContent()) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + ) + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets the associated configuration. */ + Configuration getConfiguration() { none() } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { + result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) + } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { + result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) + } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + Configuration config; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override Configuration getConfiguration() { result = config } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), + result.getConfiguration()) + } + + predicate isSource() { + sourceNode(node, state, config) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + Configuration config; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override Configuration getConfiguration() { result = config } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) + } + + predicate isSink() { + sinkNode(node, state, config) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStep(mid.getNodeEx(), node, config) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + config = mid.getConfiguration() + or + additionalLocalFlowStep(mid.getNodeEx(), node, config) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) and + config = mid.getConfiguration() + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) and + config = mid.getConfiguration() + ) + or + jumpStep(mid.getNodeEx(), node, config) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() and + config = mid.getConfiguration() + or + additionalJumpStep(mid.getNodeEx(), node, config) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) and + config = mid.getConfiguration() + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) and + config = mid.getConfiguration() + or + partialPathStoreStep(mid, _, _, node, ap) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + config = mid.getConfiguration() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc, config) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0, config) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) + or + partialPathOutOfCallable(mid, node, state, cc, ap, config) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap, config) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + store(midNode, tc, node, contentType, mid.getConfiguration()) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd( + PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + ) { + exists(PartialPathNodeFwd mid | + partialPathStoreStep(mid, ap1, tc, _, ap2) and + config = mid.getConfiguration() + ) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, + Configuration config + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and + ap.getHead() = tc and + pragma[only_bind_into](config) = mid.getConfiguration() and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap, Configuration config + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and + ap = mid.getAp() and + config = mid.getConfiguration() + } + + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + PartialAccessPath ap, Configuration config + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } + + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, + Configuration config + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) + | + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap, Configuration config + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + config = mid.getConfiguration() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap, Configuration config + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + config = mid.getConfiguration() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, + PartialAccessPath ap, Configuration config + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, + Configuration config + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, + TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config + ) { + localFlowStep(node, mid.getNodeEx(), config) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + config = mid.getConfiguration() + or + additionalLocalFlowStep(node, mid.getNodeEx(), config) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() and + config = mid.getConfiguration() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() and + config = mid.getConfiguration() + or + jumpStep(node, mid.getNodeEx(), config) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() and + config = mid.getConfiguration() + or + additionalJumpStep(node, mid.getNodeEx(), config) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() and + config = mid.getConfiguration() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() and + config = mid.getConfiguration() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + config = mid.getConfiguration() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node, config) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0, config) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() and + config = mid.getConfiguration() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap, config) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode, mid.getConfiguration()) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } + + pragma[nomagic] + private predicate apConsRev( + RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config + ) { + exists(PartialPathNodeRev mid | + revPartialPathReadStep(mid, ap1, c, _, ap2) and + config = mid.getConfiguration() + ) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + store(node, tc, midNode, _, config) and + ap.getHead() = c and + config = mid.getConfiguration() and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, + Configuration config + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() and + config = mid.getConfiguration() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + config = mid.getConfiguration() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap, Configuration config + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, + Configuration config + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } +} + +import FlowExploration + +private predicate partialFlow( + PartialPathNode source, PartialPathNode node, Configuration configuration +) { + source.getConfiguration() = configuration and + source.isFwdSource() and + node = source.getASuccessor+() +} + +private predicate revPartialFlow( + PartialPathNode node, PartialPathNode sink, Configuration configuration +) { + sink.getConfiguration() = configuration and + sink.isRevSink() and + node.getASuccessor+() = sink +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll index e995d19ccaa..3f82183aa65 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowNodes.qll @@ -280,6 +280,21 @@ module Public { explicitInstanceArgument(call, result.asExpr()) or implicitInstanceArgument(call, result.(ImplicitInstanceAccess).getInstanceAccess()) } + + /** A node representing an `InstanceAccessExt`. */ + class InstanceAccessNode extends Node { + InstanceAccessNode() { + this instanceof ImplicitInstanceAccess or this.asExpr() instanceof InstanceAccess + } + + /** Gets the instance access corresponding to this node. */ + InstanceAccessExt getInstanceAccess() { + result = this.(ImplicitInstanceAccess).getInstanceAccess() or result.isExplicit(this.asExpr()) + } + + /** Holds if this is an access to an object's own instance. */ + predicate isOwnInstanceAccess() { this.getInstanceAccess().isOwnInstanceAccess() } + } } private import Public diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 60af91e291b..1ded4e7bed1 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -175,11 +175,11 @@ module Public { * A class that exists for QL technical reasons only (the IPA type used * to represent component stacks needs to be bounded). */ - abstract class RequiredSummaryComponentStack extends SummaryComponentStack { + class RequiredSummaryComponentStack extends Unit { /** * Holds if the stack obtained by pushing `head` onto `tail` is required. */ - abstract predicate required(SummaryComponent c); + abstract predicate required(SummaryComponent head, SummaryComponentStack tail); } /** A callable with a flow summary. */ @@ -240,9 +240,9 @@ module Private { newtype TSummaryComponentStack = TSingletonSummaryComponentStack(SummaryComponent c) or TConsSummaryComponentStack(SummaryComponent head, SummaryComponentStack tail) { - tail.(RequiredSummaryComponentStack).required(head) + any(RequiredSummaryComponentStack x).required(head, tail) or - tail.(RequiredSummaryComponentStack).required(TParameterSummaryComponent(_)) and + any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and head = thisParam() or derivedFluentFlowPush(_, _, _, head, tail, _) @@ -890,9 +890,9 @@ module Private { } private class MkStack extends RequiredSummaryComponentStack { - MkStack() { interpretSpec(_, _, _, this) } - - override predicate required(SummaryComponent c) { interpretSpec(_, _, c, this) } + override predicate required(SummaryComponent head, SummaryComponentStack tail) { + interpretSpec(_, _, head, tail) + } } private class SummarizedCallableExternal extends SummarizedCallable { diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index b1840e56212..59608d792f2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -92,8 +92,6 @@ private module Cached { ) or FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) - or - entrypointFieldStep(src, sink) } /** @@ -103,6 +101,7 @@ private module Cached { cached predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { localAdditionalTaintStep(src, sink) or + entrypointFieldStep(src, sink) or any(AdditionalTaintStep a).step(src, sink) } diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll b/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll index 13efdce9a9d..17c8e09eabb 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadEnumConstant.qll @@ -60,7 +60,7 @@ predicate exception(EnumConstant e) { ) or // Entire `Enum` annotated with reflective annotation. - exists(ReflectiveAccessAnnotation ann | ann = t.getAnAnnotation()) + t.getAnAnnotation() instanceof ReflectiveAccessAnnotation ) or // Enum field annotated with reflective annotation. diff --git a/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll index b57d4cbc277..a96565c606e 100644 --- a/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/frameworks/CamelEntryPoints.qll @@ -12,6 +12,6 @@ import semmle.code.java.frameworks.Camel class CamelMessageCallableEntryPoint extends CallableEntryPoint { CamelMessageCallableEntryPoint() { exists(CamelTargetClass camelTargetClass | this = camelTargetClass.getACamelCalledMethod()) or - exists(CamelConsumeMethod consumeMethod | this = consumeMethod) + this instanceof CamelConsumeMethod } } diff --git a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll index e42da4db357..a87050966b2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Mockito.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Mockito.qll @@ -357,7 +357,7 @@ class MockitoSettableField extends Field { MockitoSettableField() { not this.isFinal() and not this.isStatic() and - exists(MockitoMockInjectedClass injectedClass | injectedClass = this.getDeclaringType()) + this.getDeclaringType() instanceof MockitoMockInjectedClass } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/Networking.qll b/java/ql/lib/semmle/code/java/frameworks/Networking.qll index 6e5ad743d44..daa1f4ca8f9 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Networking.qll @@ -14,6 +14,11 @@ class TypeSocket extends RefType { TypeSocket() { this.hasQualifiedName("java.net", "Socket") } } +/** The type `javax.net.SocketFactory` */ +class TypeSocketFactory extends RefType { + TypeSocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } +} + /** The type `java.net.URL`. */ class TypeUrl extends RefType { TypeUrl() { this.hasQualifiedName("java.net", "URL") } @@ -42,6 +47,15 @@ class SocketGetInputStreamMethod extends Method { } } +/** The method `java.net.Socket::getOutputStream`. */ +class SocketGetOutputStreamMethod extends Method { + SocketGetOutputStreamMethod() { + this.getDeclaringType() instanceof TypeSocket and + this.hasName("getOutputStream") and + this.hasNoParameters() + } +} + /** A method or constructor call that returns a new `URI`. */ class UriCreation extends Call { UriCreation() { @@ -143,6 +157,22 @@ class UrlOpenConnectionMethod extends Method { } } +/** The method `javax.net.SocketFactory::createSocket`. */ +class CreateSocketMethod extends Method { + CreateSocketMethod() { + this.hasName("createSocket") and + this.getDeclaringType().getASupertype*() instanceof TypeSocketFactory + } +} + +/** The method `javax.net.Socket::connect`. */ +class SocketConnectMethod extends Method { + SocketConnectMethod() { + this.hasName("connect") and + this.getDeclaringType() instanceof TypeSocket + } +} + /** * A string matching private host names of IPv4 and IPv6, which only matches the host portion therefore checking for port is not necessary. * Several examples are localhost, reserved IPv4 IP addresses including 127.0.0.1, 10.x.x.x, 172.16.x,x, 192.168.x,x, and reserved IPv6 addresses including [0:0:0:0:0:0:0:1] and [::1] diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index d9988e31f67..81f334015bd 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -10,7 +10,7 @@ import semmle.code.java.Type */ library class ServletRequest extends RefType { ServletRequest() { - hasQualifiedName("javax.servlet", "ServletRequest") or + this.hasQualifiedName("javax.servlet", "ServletRequest") or this instanceof HttpServletRequest } } @@ -19,7 +19,7 @@ library class ServletRequest extends RefType { * The interface `javax.servlet.http.HttpServletRequest`. */ library class HttpServletRequest extends RefType { - HttpServletRequest() { hasQualifiedName("javax.servlet.http", "HttpServletRequest") } + HttpServletRequest() { this.hasQualifiedName("javax.servlet.http", "HttpServletRequest") } } /** @@ -28,13 +28,13 @@ library class HttpServletRequest extends RefType { */ library class ServletRequestGetParameterMethod extends Method { ServletRequestGetParameterMethod() { - getDeclaringType() instanceof ServletRequest and + this.getDeclaringType() instanceof ServletRequest and ( - hasName("getParameter") or - hasName("getParameterValues") + this.hasName("getParameter") or + this.hasName("getParameterValues") ) and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -43,9 +43,9 @@ library class ServletRequestGetParameterMethod extends Method { */ library class ServletRequestGetParameterNamesMethod extends Method { ServletRequestGetParameterNamesMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getParameterNames") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getParameterNames") and + this.getNumberOfParameters() = 0 } } @@ -54,9 +54,9 @@ library class ServletRequestGetParameterNamesMethod extends Method { */ library class ServletRequestGetParameterMapMethod extends Method { ServletRequestGetParameterMapMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getParameterMap") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getParameterMap") and + this.getNumberOfParameters() = 0 } } @@ -65,9 +65,9 @@ library class ServletRequestGetParameterMapMethod extends Method { */ library class HttpServletRequestGetQueryStringMethod extends Method { HttpServletRequestGetQueryStringMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getQueryString") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getQueryString") and + this.getNumberOfParameters() = 0 } } @@ -76,9 +76,9 @@ library class HttpServletRequestGetQueryStringMethod extends Method { */ class HttpServletRequestGetPathMethod extends Method { HttpServletRequestGetPathMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getPathInfo") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getPathInfo") and + this.getNumberOfParameters() = 0 } } @@ -87,10 +87,10 @@ class HttpServletRequestGetPathMethod extends Method { */ library class HttpServletRequestGetHeaderMethod extends Method { HttpServletRequestGetHeaderMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeader") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeader") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -99,10 +99,10 @@ library class HttpServletRequestGetHeaderMethod extends Method { */ library class HttpServletRequestGetHeadersMethod extends Method { HttpServletRequestGetHeadersMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeaders") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeaders") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -111,9 +111,9 @@ library class HttpServletRequestGetHeadersMethod extends Method { */ library class HttpServletRequestGetHeaderNamesMethod extends Method { HttpServletRequestGetHeaderNamesMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getHeaderNames") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getHeaderNames") and + this.getNumberOfParameters() = 0 } } @@ -122,9 +122,9 @@ library class HttpServletRequestGetHeaderNamesMethod extends Method { */ class HttpServletRequestGetRequestURLMethod extends Method { HttpServletRequestGetRequestURLMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRequestURL") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRequestURL") and + this.getNumberOfParameters() = 0 } } @@ -133,9 +133,9 @@ class HttpServletRequestGetRequestURLMethod extends Method { */ class HttpServletRequestGetRequestURIMethod extends Method { HttpServletRequestGetRequestURIMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRequestURI") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRequestURI") and + this.getNumberOfParameters() = 0 } } @@ -144,9 +144,9 @@ class HttpServletRequestGetRequestURIMethod extends Method { */ library class HttpServletRequestGetRemoteUserMethod extends Method { HttpServletRequestGetRemoteUserMethod() { - getDeclaringType() instanceof HttpServletRequest and - hasName("getRemoteUser") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof HttpServletRequest and + this.hasName("getRemoteUser") and + this.getNumberOfParameters() = 0 } } @@ -155,8 +155,8 @@ library class HttpServletRequestGetRemoteUserMethod extends Method { */ library class ServletRequestGetBodyMethod extends Method { ServletRequestGetBodyMethod() { - getDeclaringType() instanceof ServletRequest and - (hasName("getInputStream") or hasName("getReader")) + this.getDeclaringType() instanceof ServletRequest and + (this.hasName("getInputStream") or this.hasName("getReader")) } } @@ -166,7 +166,7 @@ library class ServletRequestGetBodyMethod extends Method { */ class ServletResponse extends RefType { ServletResponse() { - hasQualifiedName("javax.servlet", "ServletResponse") or + this.hasQualifiedName("javax.servlet", "ServletResponse") or this instanceof HttpServletResponse } } @@ -175,7 +175,7 @@ class ServletResponse extends RefType { * The interface `javax.servlet.http.HttpServletResponse`. */ class HttpServletResponse extends RefType { - HttpServletResponse() { hasQualifiedName("javax.servlet.http", "HttpServletResponse") } + HttpServletResponse() { this.hasQualifiedName("javax.servlet.http", "HttpServletResponse") } } /** @@ -183,11 +183,11 @@ class HttpServletResponse extends RefType { */ class HttpServletResponseSendErrorMethod extends Method { HttpServletResponseSendErrorMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("sendError") and - getNumberOfParameters() = 2 and - getParameter(0).getType().hasName("int") and - getParameter(1).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("sendError") and + this.getNumberOfParameters() = 2 and + this.getParameter(0).getType().hasName("int") and + this.getParameter(1).getType() instanceof TypeString } } @@ -196,8 +196,8 @@ class HttpServletResponseSendErrorMethod extends Method { */ class ServletRequestGetRequestDispatcherMethod extends Method { ServletRequestGetRequestDispatcherMethod() { - getDeclaringType() instanceof ServletRequest and - hasName("getRequestDispatcher") + this.getDeclaringType() instanceof ServletRequest and + this.hasName("getRequestDispatcher") } } @@ -206,10 +206,10 @@ class ServletRequestGetRequestDispatcherMethod extends Method { */ class HttpServletResponseSendRedirectMethod extends Method { HttpServletResponseSendRedirectMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("sendRedirect") and - getNumberOfParameters() = 1 and - getParameter(0).getType() instanceof TypeString + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("sendRedirect") and + this.getNumberOfParameters() = 1 and + this.getParameter(0).getType() instanceof TypeString } } @@ -218,9 +218,9 @@ class HttpServletResponseSendRedirectMethod extends Method { */ class ServletResponseGetWriterMethod extends Method { ServletResponseGetWriterMethod() { - getDeclaringType() instanceof ServletResponse and - hasName("getWriter") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletResponse and + this.hasName("getWriter") and + this.getNumberOfParameters() = 0 } } @@ -229,15 +229,15 @@ class ServletResponseGetWriterMethod extends Method { */ class ServletResponseGetOutputStreamMethod extends Method { ServletResponseGetOutputStreamMethod() { - getDeclaringType() instanceof ServletResponse and - hasName("getOutputStream") and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof ServletResponse and + this.hasName("getOutputStream") and + this.getNumberOfParameters() = 0 } } /** The class `javax.servlet.http.Cookie`. */ library class TypeCookie extends Class { - TypeCookie() { hasQualifiedName("javax.servlet.http", "Cookie") } + TypeCookie() { this.hasQualifiedName("javax.servlet.http", "Cookie") } } /** @@ -245,9 +245,9 @@ library class TypeCookie extends Class { */ library class CookieGetValueMethod extends Method { CookieGetValueMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getValue") and - getReturnType() instanceof TypeString + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getValue") and + this.getReturnType() instanceof TypeString } } @@ -256,10 +256,10 @@ library class CookieGetValueMethod extends Method { */ library class CookieGetNameMethod extends Method { CookieGetNameMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getName") and - getReturnType() instanceof TypeString and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getName") and + this.getReturnType() instanceof TypeString and + this.getNumberOfParameters() = 0 } } @@ -268,10 +268,10 @@ library class CookieGetNameMethod extends Method { */ library class CookieGetCommentMethod extends Method { CookieGetCommentMethod() { - getDeclaringType() instanceof TypeCookie and - hasName("getComment") and - getReturnType() instanceof TypeString and - getNumberOfParameters() = 0 + this.getDeclaringType() instanceof TypeCookie and + this.hasName("getComment") and + this.getReturnType() instanceof TypeString and + this.getNumberOfParameters() = 0 } } @@ -280,8 +280,8 @@ library class CookieGetCommentMethod extends Method { */ class ResponseAddCookieMethod extends Method { ResponseAddCookieMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("addCookie") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("addCookie") } } @@ -290,8 +290,8 @@ class ResponseAddCookieMethod extends Method { */ class ResponseAddHeaderMethod extends Method { ResponseAddHeaderMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("addHeader") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("addHeader") } } @@ -300,8 +300,8 @@ class ResponseAddHeaderMethod extends Method { */ class ResponseSetHeaderMethod extends Method { ResponseSetHeaderMethod() { - getDeclaringType() instanceof HttpServletResponse and - hasName("setHeader") + this.getDeclaringType() instanceof HttpServletResponse and + this.hasName("setHeader") } } @@ -309,7 +309,7 @@ class ResponseSetHeaderMethod extends Method { * A class that has `javax.servlet.Servlet` as an ancestor. */ class ServletClass extends Class { - ServletClass() { getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") } + ServletClass() { this.getAnAncestor().hasQualifiedName("javax.servlet", "Servlet") } } /** @@ -320,13 +320,13 @@ class ServletClass extends Class { */ class ServletWebXMLListenerType extends RefType { ServletWebXMLListenerType() { - hasQualifiedName("javax.servlet", "ServletContextAttributeListener") or - hasQualifiedName("javax.servlet", "ServletContextListener") or - hasQualifiedName("javax.servlet", "ServletRequestAttributeListener") or - hasQualifiedName("javax.servlet", "ServletRequestListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionAttributeListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionIdListener") or - hasQualifiedName("javax.servlet.http", "HttpSessionListener") + this.hasQualifiedName("javax.servlet", "ServletContextAttributeListener") or + this.hasQualifiedName("javax.servlet", "ServletContextListener") or + this.hasQualifiedName("javax.servlet", "ServletRequestAttributeListener") or + this.hasQualifiedName("javax.servlet", "ServletRequestListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionAttributeListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionIdListener") or + this.hasQualifiedName("javax.servlet.http", "HttpSessionListener") // Listeners that are not configured in `web.xml`: // - `HttpSessionActivationListener` // - `HttpSessionBindingListener` diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll index c019dc11bd8..41ad2d14968 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Android.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Android.qll @@ -67,6 +67,14 @@ class AndroidActivity extends ExportableAndroidComponent { AndroidActivity() { getASuperTypeStar(this).hasQualifiedName("android.app", "Activity") } } +/** The method `setResult` of the class `android.app.Activity`. */ +class ActivitySetResultMethod extends Method { + ActivitySetResultMethod() { + this.getDeclaringType().hasQualifiedName("android.app", "Activity") and + this.hasName("setResult") + } +} + /** An Android service. */ class AndroidService extends ExportableAndroidComponent { AndroidService() { getASuperTypeStar(this).hasQualifiedName("android.app", "Service") } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll index 528162fe4d4..99e875c20c1 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll @@ -2,15 +2,15 @@ import java -/** The class `android.app.Fragment` */ -class Fragment extends Class { - Fragment() { this.hasQualifiedName("android.app", "Fragment") } +/** The class `android.app.Fragment`. */ +class AndroidFragment extends Class { + AndroidFragment() { this.getASupertype*().hasQualifiedName("android.app", "Fragment") } } /** The method `instantiate` of the class `android.app.Fragment`. */ class FragmentInstantiateMethod extends Method { FragmentInstantiateMethod() { - this.getDeclaringType() instanceof Fragment and + this.getDeclaringType() instanceof AndroidFragment and this.hasName("instantiate") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index d77e4a5b86d..51f3b577420 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -148,6 +148,31 @@ predicate allowIntentExtrasImplicitRead(DataFlow::Node node, DataFlow::Content c ) } +/** + * The fields to grant URI permissions of the class `android.content.Intent`: + * + * - `Intent.FLAG_GRANT_READ_URI_PERMISSION` + * - `Intent.FLAG_GRANT_WRITE_URI_PERMISSION` + * - `Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION` + * - `Intent.FLAG_GRANT_PREFIX_URI_PERMISSION` + */ +class GrantUriPermissionFlag extends Field { + GrantUriPermissionFlag() { + this.getDeclaringType() instanceof TypeIntent and + this.getName().matches("FLAG_GRANT_%_URI_PERMISSION") + } +} + +/** The field `Intent.FLAG_GRANT_READ_URI_PERMISSION`. */ +class GrantReadUriPermissionFlag extends GrantUriPermissionFlag { + GrantReadUriPermissionFlag() { this.hasName("FLAG_GRANT_READ_URI_PERMISSION") } +} + +/** The field `Intent.FLAG_GRANT_WRITE_URI_PERMISSION`. */ +class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag { + GrantWriteUriPermissionFlag() { this.hasName("FLAG_GRANT_WRITE_URI_PERMISSION") } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll new file mode 100644 index 00000000000..8eb2aecb4d2 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll @@ -0,0 +1,119 @@ +/** Provides a remote flow source for Android's `Activity.onActivityResult` method. */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.internal.DataFlowForOnActivityResult +private import semmle.code.java.frameworks.android.Android +private import semmle.code.java.frameworks.android.Fragment +private import semmle.code.java.frameworks.android.Intent + +/** + * The data Intent parameter in the `onActivityResult` method. + */ +class OnActivityResultIncomingIntent extends DataFlow::Node { + OnActivityResultIncomingIntent() { + exists(Method onActivityResult | + onActivityResult.getDeclaringType() instanceof ActivityOrFragment and + onActivityResult.hasName("onActivityResult") and + this.asParameter() = onActivityResult.getParameter(2) + ) + } + + /** + * Holds if this node is a remote flow source. + * + * This is only a source when the Activity or Fragment that implements `onActivityResult` is + * also using an implicit Intent to start another Activity with `startActivityForResult`. This + * means that a malicious application can intercept it to start itself and return an arbitrary + * Intent to `onActivityResult`. + */ + predicate isRemoteSource() { + exists( + ImplicitStartActivityForResultConf conf, RefType startingType, Expr startActivityForResultArg + | + conf.hasFlowToExpr(startActivityForResultArg) and + // startingType is the class enclosing the method that calls `startActivityForResult`. + startingType = startActivityForResultArg.getEnclosingCallable().getDeclaringType() + | + // startingType itself defines an `onActivityResult` method: + startingType = this.getEnclosingCallable().getDeclaringType() + or + // A fragment calls `startActivityForResult` + // and the activity it belongs to defines `onActivityResult`. + exists(MethodAccess ma | + ma.getMethod().hasName(["add", "attach", "replace"]) and + ma.getMethod() + .getDeclaringType() + .hasQualifiedName(["android.app", "android.support.v4.app", "androidx.fragment.app"], + "FragmentTransaction") and + ma.getAnArgument().getType() = startingType + or + ma.getMethod().hasName("show") and + ma.getMethod() + .getDeclaringType() + .getASupertype*() + .hasQualifiedName(["android.app", "android.support.v4.app", "androidx.fragment.app"], + "DialogFragment") and + startingType = ma.getQualifier().getType() + | + ma.getEnclosingCallable().getDeclaringType() = + this.getEnclosingCallable().getDeclaringType() + ) + ) + } +} + +/** + * A data flow configuration for implicit intents being used in `startActivityForResult`. + */ +private class ImplicitStartActivityForResultConf extends DataFlowForOnActivityResult::Configuration { + ImplicitStartActivityForResultConf() { this = "ImplicitStartActivityForResultConf" } + + override predicate isSource(DataFlow::Node source) { + exists(ClassInstanceExpr cc | + cc.getConstructedType() instanceof TypeIntent and source.asExpr() = cc + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess startActivityForResult | + startActivityForResult.getMethod().hasName("startActivityForResult") and + startActivityForResult.getMethod().getDeclaringType().getASupertype*() instanceof + ActivityOrFragment and + sink.asExpr() = startActivityForResult.getArgument(0) + ) + } + + override predicate isBarrier(DataFlow::Node barrier) { + barrier instanceof ExplicitIntentSanitizer + } + + override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + // Wrapping the Intent in a chooser + exists(MethodAccess ma, Method m | + ma.getMethod() = m and + m.hasName("createChooser") and + m.getDeclaringType() instanceof TypeIntent + | + node1.asExpr() = ma.getArgument(0) and + node2.asExpr() = ma + ) + or + // Using the copy constructor + exists(ClassInstanceExpr cie | + cie.getConstructedType() instanceof TypeIntent and + cie.getArgument(0).getType() instanceof TypeIntent + | + node1.asExpr() = cie.getArgument(0) and + node2.asExpr() = cie + ) + } +} + +/** An Android Activity or Fragment. */ +private class ActivityOrFragment extends Class { + ActivityOrFragment() { + this instanceof AndroidActivity or + this instanceof AndroidFragment + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll index ac688503e6d..5538dbd4163 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll @@ -5,6 +5,36 @@ private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.ExternalFlow +/** The class `androidx.slice.SliceProvider`. */ +class SliceProvider extends Class { + SliceProvider() { this.hasQualifiedName("androidx.slice", "SliceProvider") } +} + +/** + * An additional value step for modeling the lifecycle of a `SliceProvider`. + * It connects the `PostUpdateNode` of any update done to the provider object in + * `onCreateSliceProvider` to the instance parameter of `onBindSlice`. + */ +private class SliceProviderLifecycleStep extends AdditionalValueStep { + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { + exists(Method onCreate, Method onBind, RefType declaringClass | + declaringClass.getASupertype*() instanceof SliceProvider and + onCreate.getDeclaringType() = declaringClass and + onCreate.hasName("onCreateSliceProvider") and + onBind.getDeclaringType() = declaringClass and + onBind.hasName("onBindSlice") + | + node1 + .(DataFlow::PostUpdateNode) + .getPreUpdateNode() + .(DataFlow::InstanceAccessNode) + .isOwnInstanceAccess() and + node1.getEnclosingCallable() = onCreate and + node2.(DataFlow::InstanceParameterNode).getEnclosingCallable() = onBind + ) + } +} + private class SliceActionsInheritTaint extends DataFlow::SyntheticFieldContent, TaintInheritingContent { SliceActionsInheritTaint() { this.getField().matches("androidx.slice.Slice.action") } diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll index 3c989fff37f..2c3d79f2798 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IO.qll @@ -1,34 +1,18 @@ -/** Definitions related to the Apache Commons IO library. */ +/** Custom definitions related to the Apache Commons IO library. */ import java +import IOGenerated private import semmle.code.java.dataflow.ExternalFlow -private class CommonsIOSummaryCsv extends SummaryModelCsv { +// TODO: manual models that were not generated yet +private class ApacheCommonsIOCustomSummaryCsv extends SummaryModelCsv { override predicate row(string row) { row = [ - "org.apache.commons.io;IOUtils;false;buffer;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;copy;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;copyLarge;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;read;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;readLines;;;Argument[0];ReturnValue;taint", "org.apache.commons.io;IOUtils;false;toBufferedInputStream;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toBufferedReader;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toByteArray;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toCharArray;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toInputStream;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;toString;;;Argument[0];ReturnValue;taint", - "org.apache.commons.io;IOUtils;false;write;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeChunked;;;Argument[0];Argument[1];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[0];Argument[2];taint", - "org.apache.commons.io;IOUtils;false;writeLines;;;Argument[1];Argument[2];taint" + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(Reader,String);;Argument[0];ReturnValue;taint", ] } } diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll new file mode 100644 index 00000000000..87bdcf12ce6 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/apache/IOGenerated.qll @@ -0,0 +1,684 @@ +/** Definitions of taint steps in the IO framework */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class IOSinksCsv extends SinkModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.file;PathFilter;true;accept;(Path,BasicFileAttributes);;Argument[0];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Argument[0];open-url", + "org.apache.commons.io.file;PathUtils;false;newOutputStream;(Path,boolean);;Argument[0];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filter;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterList;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.filefilter;FileFilterUtils;true;filterSet;(IOFileFilter,File[]);;Argument[1];create-file", + "org.apache.commons.io.input;Tailer$Tailable;true;getRandomAccess;(String);;Argument[-1];create-file", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URL);;Argument[0];open-url", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,CharsetEncoder,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String);;Argument[0];create-file", + "org.apache.commons.io.output;FileWriterWithEncoding;true;FileWriterWithEncoding;(String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File);;Argument[0];create-file", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,FileFilter,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyDirectoryToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFile;(File,File,boolean,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyInputStreamToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToDirectory;(Iterable,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyToFile;(InputStream,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[0];open-url", + "org.apache.commons.io;FileUtils;true;copyURLToFile;(URL,File,int,int);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectory;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveDirectoryToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFile;(File,File,CopyOption[]);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveFileToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;moveToDirectory;(File,File,boolean);;Argument[1];create-file", + "org.apache.commons.io;FileUtils;true;newOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;openOutputStream;(File,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;touch;(File);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;write;(File,CharSequence,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[]);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeByteArrayToFile;(File,byte[],int,int,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeLines;(File,String,Collection,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,Charset,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;FileUtils;true;writeStringToFile;(File,String,boolean);;Argument[0];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;copy;(URL,File);;Argument[1];create-file", + "org.apache.commons.io;IOUtils;true;copy;(URL,OutputStream);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toByteArray;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URI,String);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,Charset);;Argument[0];open-url", + "org.apache.commons.io;IOUtils;true;toString;(URL,String);;Argument[0];open-url", + "org.apache.commons.io;RandomAccessFileMode;false;create;(File);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(Path);;Argument[0];create-file", + "org.apache.commons.io;RandomAccessFileMode;false;create;(String);;Argument[0];create-file" + ] + } +} + +private class IOSourcesCsv extends SourceModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io;IOUtils;true;resourceToByteArray;(String,ClassLoader);;ReturnValue;remote", + "org.apache.commons.io;IOUtils;true;toByteArray;(URI);;ReturnValue;remote" + ] + } +} + +private class IOSummaryCsv extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Comparator[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.comparator;CompositeFileComparator;true;CompositeFileComparator;(Iterable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.comparator;CompositeFileComparator;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URI);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file.spi;FileSystemProviders;true;getFileSystemProvider;(URL);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;AccumulatorPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getDirList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;getFileList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withBigIntegerCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;AccumulatorPathVisitor;true;withLongCounters;(PathFilter,PathFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CleaningPathVisitor;true;CleaningPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;CopyDirectoryVisitor;(PathCounters,PathFilter,PathFilter,Path,Path,CopyOption[]);;Argument[5];Argument[-1];taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getCopyOptions;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getSourceDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CopyDirectoryVisitor;true;getTargetDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getByteCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getDirectoryCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;Counters$PathCounters;true;getFileCounter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;CountingPathVisitor;(PathCounters,PathFilter,PathFilter);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;CountingPathVisitor;true;getPathCounters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,DeleteOption[],String[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,LinkOption[],DeleteOption[],String[]);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DeletingPathVisitor;true;DeletingPathVisitor;(PathCounters,String[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;DirectoryStreamFilter;(PathFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.file;DirectoryStreamFilter;true;getPathFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;ArrayElement of Argument[2];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyDirectory;(Path,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFile;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;copyFileToDirectory;(URL,Path,CopyOption[]);;Element of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;delete;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;deleteDirectory;(Path,LinkOption[],DeleteOption[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;setReadOnly;(Path,boolean,LinkOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,Path,Set,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,String,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;visitFileTree;(FileVisitor,URI);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.file;PathUtils;false;writeString;(Path,CharSequence,Charset,OpenOption[]);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;AgeFileFilter;(Instant,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AgeFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;AndFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;AndFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;addFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;getFileFilters;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;ConditionalFileFilter;true;setFileFilters;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;DelegateFileFilter;(FilenameFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;DelegateFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileEqualsFileFilter;true;FileEqualsFileFilter;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;and;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;andFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;asFileFilter;(FilenameFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(String,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;magicNumberFileFilter;(byte[],long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeCVSAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeDirectoryOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeFileOnly;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;makeSVNAware;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;nameFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;notFileFilter;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;or;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;orFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;prefixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;suffixFileFilter;(String,IOCase);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;FileFilterUtils;true;toList;(IOFileFilter[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;and;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;negate;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;IOFileFilter;true;or;(IOFileFilter);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(String,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;MagicNumberFileFilter;(byte[],long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;MagicNumberFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;NameFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NameFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;NotFileFilter;(IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;NotFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter,IOFileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;OrFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;addFileFilter;(IOFileFilter[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;OrFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;PathEqualsFileFilter;true;PathEqualsFileFilter;(Path);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PathVisitorFileFilter;true;PathVisitorFileFilter;(PathVisitor);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;PrefixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;PrefixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;RegexFileFilter;(Pattern,Function);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.filefilter;RegexFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;SuffixFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;SuffixFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(List,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;WildcardFileFilter;(String[],IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFileFilter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.filefilter;WildcardFilter;true;WildcardFilter;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularBufferInputStream;true;CircularBufferInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;CircularByteBuffer;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input.buffer;PeekableInputStream;true;PeekableInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,ByteOrderMark[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;BOMInputStream;(InputStream,boolean,ByteOrderMark[]);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOM;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BOMInputStream;true;getBOMCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedInputStream;true;BoundedInputStream;(InputStream,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BoundedReader;true;BoundedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenInputStream;true;BrokenInputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;BrokenReader;true;BrokenReader;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;CharSequenceReader;(CharSequence,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;CharSequenceReader;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;CharacterFilterReader;true;CharacterFilterReader;(Reader,IntPredicate);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CircularInputStream;true;CircularInputStream;(byte[],long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ClassLoaderObjectInputStream;true;ClassLoaderObjectInputStream;(ClassLoader,InputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;CloseShieldInputStream;true;wrap;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;InfiniteCircularInputStream;true;InfiniteCircularInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream$MessageDigestMaintainingObserver;true;MessageDigestMaintainingObserver;(MessageDigest);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;MessageDigestCalculatingInputStream;(InputStream,MessageDigest);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;MessageDigestCalculatingInputStream;true;getMessageDigest;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ObservableInputStream;true;ObservableInputStream;(InputStream,Observer[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ObservableInputStream;true;add;(Observer);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ObservableInputStream;true;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;RandomAccessFileInputStream;(RandomAccessFile,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;RandomAccessFileInputStream;true;getRandomAccessFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReadAheadInputStream;true;ReadAheadInputStream;(InputStream,int,ExecutorService);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,Charset,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,CharsetEncoder,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReaderInputStream;true;ReaderInputStream;(Reader,String,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;readLines;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;ReversedLinesFileReader;true;toString;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Iterable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;SequenceReader;true;SequenceReader;(Reader[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Path,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;Builder;(Tailable,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withBufferSize;(int);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withCharset;(Charset);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer$Builder;true;withDelayDuration;(Duration);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer$Builder;true;withReOpen;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withStartThread;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer$Builder;true;withTailFromEnd;(boolean);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;Tailer;(File,TailerListener,long,boolean,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,Charset,TailerListener,long,boolean,boolean,int);;Argument[2];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,boolean,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;create;(File,TailerListener,long,boolean,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getDelayDuration;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;Tailer;true;getTailable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeInputStream;true;TeeInputStream;(InputStream,OutputStream,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TeeReader;true;TeeReader;(Reader,Writer,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;TimestampedObserver;true;getCloseInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;getOpenInstant;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;TimestampedObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;UncheckedBufferedReader;(Reader,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UncheckedBufferedReader;true;on;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UncheckedFilterInputStream;true;on;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.input;UnixLineEndingInputStream;true;UnixLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;UnsynchronizedByteArrayInputStream;true;UnsynchronizedByteArrayInputStream;(byte[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;WindowsLineEndingInputStream;true;WindowsLineEndingInputStream;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(InputStream,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;XmlStreamReader;(URLConnection,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReader;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReader;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;XmlStreamReaderException;(String,String,String,String,String,String);;Argument[5];Argument[-1];taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getBomEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getContentTypeMime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.input;XmlStreamReaderException;true;getXmlGuessEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,Collection);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;FileAlterationMonitor;(long,FileAlterationObserver[]);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;addObserver;(FileAlterationObserver);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;getObservers;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationMonitor;false;setThreadFactory;(ThreadFactory);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(File,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;FileAlterationObserver;(String,FileFilter,IOCase);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;addListener;(FileAlterationListener);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getDirectory;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getFileFilter;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;getListeners;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileAlterationObserver;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;FileEntry;(FileEntry,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;getChildren;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getLastModifiedFileTime;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;getParent;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;newChildInstance;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.monitor;FileEntry;true;setChildren;(FileEntry[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setLastModified;(FileTime);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.monitor;FileEntry;true;setName;(String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toByteArray;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(Charset);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;toString;(String);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;write;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AbstractByteArrayOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;AppendableOutputStream;(Appendable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AppendableOutputStream;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;AppendableWriter;true;AppendableWriter;(Appendable);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;AppendableWriter;true;getAppendable;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;BrokenOutputStream;true;BrokenOutputStream;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;BrokenWriter;true;BrokenWriter;(Supplier);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ChunkedOutputStream;true;ChunkedOutputStream;(OutputStream,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;CloseShieldOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;CloseShieldOutputStream;true;wrap;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;CountingOutputStream;true;CountingOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;DeferredFileOutputStream;(int,int,String,String,File);;Argument[4];Argument[-1];taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getData;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;DeferredFileOutputStream;true;writeTo;(OutputStream);;Argument[-1];Argument[0];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,Charset,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,String,boolean,String);;Argument[3];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(File,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;LockableFileWriter;true;LockableFileWriter;(String,boolean,String);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyCollectionWriter;true;ProxyCollectionWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ProxyOutputStream;true;ProxyOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;StringBuilderWriter;(StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;StringBuilderWriter;true;getBuilder;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;StringBuilderWriter;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;TaggedOutputStream;true;TaggedOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeOutputStream;true;TeeOutputStream;(OutputStream,OutputStream);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Collection);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;TeeWriter;true;TeeWriter;(Writer[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;ThresholdingOutputStream;true;ThresholdingOutputStream;(int,IOConsumer,IOFunction);;Argument[2];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedAppendable;true;on;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;UncheckedFilterOutputStream;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;UncheckedFilterOutputStream;true;on;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,Charset,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,CharsetDecoder,int,boolean);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;WriterOutputStream;true;WriterOutputStream;(Writer,String,int,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(File,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;XmlStreamWriter;(OutputStream,String);;Argument[1];Argument[-1];taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getDefaultEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.output;XmlStreamWriter;true;getEncoding;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;ValidatingObjectInputStream;(InputStream);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;accept;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(ClassNameMatcher);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Class[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(Pattern);;Argument[0];ReturnValue;taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[-1];ReturnValue;value", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io.serialization;ValidatingObjectInputStream;true;reject;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;ByteOrderMark;(String,int[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;ByteOrderMark;true;getCharsetName;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;ByteOrderMark;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(String,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;CopyUtils;true;copy;(byte[],Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(File,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;CancelException;(String,File,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;DirectoryWalker$CancelException;true;getFile;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;getDeleteFailures;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(File,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;FileCleaningTracker;true;track;(String,Object,FileDeleteStrategy);;Argument[2];Argument[-1];taint", + "org.apache.commons.io;FileDeleteStrategy;true;toString;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;FileSystem;false;toLegalFileName;(String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;checksum;(File,Checksum);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;convertFileCollectionToFileArray;(Collection);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;delete;(File);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(File,String[]);;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;getFile;(String[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FileUtils;true;toURLs;(File[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;concat;(String,String);;Argument[1];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getBaseName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getFullPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getName;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPath;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPathNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;getPrefix;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalize;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;normalizeNoEndSeparator;(String,boolean);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;FilenameUtils;true;removeExtension;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;HexDump;true;dump;(byte[],long,OutputStream,int);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(List);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;IOExceptionList;true;IOExceptionList;(String,List);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;IOExceptionList;true;getCause;(int);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOExceptionList;true;getCauseList;(Class);;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(OutputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;buffer;(Writer,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,OutputStream,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(InputStream,Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Appendable,CharBuffer);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copy;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,byte[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(InputStream,OutputStream,long,long,byte[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[0];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,char[]);;Argument[2];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[0];Argument[4];taint", + "org.apache.commons.io;IOUtils;true;copyLarge;(Reader,Writer,long,long,char[]);;Argument[4];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;lineIterator;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;read;(Reader,char[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,byte[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readFully;(ReadableByteChannel,ByteBuffer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[]);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readFully;(Reader,char[],int,int);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;readLines;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toBufferedReader;(Reader,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(InputStream,long);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toByteArray;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toCharArray;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(CharSequence,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toInputStream;(String,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,Charset);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(InputStream,String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(Reader);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;toString;(byte[],String);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(CharSequence,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(String,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(StringBuffer,Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(byte[],Writer,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,Charset);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],OutputStream,String);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;write;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeChunked;(char[],Writer);;Argument[0];Argument[1];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,Charset);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,OutputStream,String);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writeLines;(Collection,String,Writer);;Argument[1];Argument[2];taint", + "org.apache.commons.io;IOUtils;true;writer;(Appendable);;Argument[0];ReturnValue;taint", + "org.apache.commons.io;LineIterator;true;LineIterator;(Reader);;Argument[0];Argument[-1];taint", + "org.apache.commons.io;LineIterator;true;nextLine;();;Argument[-1];ReturnValue;taint", + "org.apache.commons.io;TaggedIOException;true;TaggedIOException;(IOException,Serializable);;Argument[1];Argument[-1];taint", + "org.apache.commons.io;TaggedIOException;true;getTag;();;Argument[-1];ReturnValue;taint" + ] + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll index 45157b4993e..b536539670e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll +++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll @@ -1,6 +1,8 @@ /** Definitions related to the Apache Commons Lang library. */ import java +import Lang2Generated +import Lang3Generated private import semmle.code.java.dataflow.FlowSteps private import semmle.code.java.dataflow.ExternalFlow @@ -27,529 +29,6 @@ class MethodApacheSerializationUtilsDeserialize extends Method { } } -/** - * Taint-propagating models for `ArrayUtils`. - */ -private class ApacheArrayUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", - "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value" - ] - } -} - -private class ApacheStringEscapeUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint" - ] - } -} - -private class ApacheStringUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint" - ] - } -} - -private class ApacheStrBuilderModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", - "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", - "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", - "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", - "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint" - ] - } -} - -private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", - "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value" - ] - } -} - /** * An Apache Commons-Lang StrBuilder method that returns `this`. */ @@ -558,329 +37,3 @@ private class ApacheStrBuilderFluentMethod extends FluentMethod { this.getReturnType().(RefType).hasQualifiedName("org.apache.commons.lang3.text", "StrBuilder") } } - -/** - * Taint-propagating models for `WordUtils`. - */ -private class ApacheWordUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint" - ] - } -} - -/** - * Taint-propagating models for `StrTokenizer`. - */ -private class ApacheStrTokenizerModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint" - ] - } -} - -/** - * Taint-propagating models for `StrLookup`. - */ -private class ApacheStrLookupModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint", - "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint" - ] - } -} - -/** - * Taint-propagating models for `StrSubstitutor`. - */ -private class ApacheStrSubstitutorModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint", - "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint", - "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint", - "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint" - ] - } -} - -/** - * Taint-propagating models for `RegexUtils`. - */ -private class ApacheRegExUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint", - "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint" - ] - } -} - -/** - * Taint-propagating models for `ObjectUtils`. - */ -private class ApacheObjectUtilsModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - // Note all the functions annotated with `taint` flow really should have `value` flow, - // but we don't support value-preserving varargs functions at the moment. - "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value", - "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value" - ] - } -} - -private class ApacheToStringBuilderModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint", - "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint", - // The following are value-preserving steps for fluent methods: - "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value" - ] - } -} - -/** - * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`. - */ -private class ApachePairModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", - "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value" - ] - } -} - -/** - * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`. - */ -private class ApacheTripleModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", - "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", - "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", - "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value", - "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value" - ] - } -} - -/** - * Value-propagating models for `MutableObject`. - */ -private class ApacheMutableObjectModel extends SummaryModelCsv { - override predicate row(string row) { - row = - [ - "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value", - "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value", - "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value" - ] - } -} diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll new file mode 100644 index 00000000000..757f28f19cf --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll @@ -0,0 +1,284 @@ +/** Definitions related to the Apache Commons Lang 2 library. */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class ApacheCommonsLangModel extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", + "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint", + "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", + "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", + "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value", + "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint", + "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint", + ] + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll new file mode 100644 index 00000000000..251f72e4c80 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll @@ -0,0 +1,436 @@ +/** Definitions related to the Apache Commons Lang 3 library. */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +private class ApacheCommonsLang3Model extends SummaryModelCsv { + override predicate row(string row) { + row = + [ + "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value", + "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value", + "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value", + "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value", + "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value", + "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint", + "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint", + "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint", + "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value", + "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value", + "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value", + "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value", + ] + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll index df3799153e4..17a19c9a228 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBean.qll @@ -233,7 +233,7 @@ class SpringBean extends SpringXMLElement { SpringBean getBeanParent() { result.getBeanIdentifier() = this.getBeanParentName() } /** Holds if this bean has a parent bean. */ - predicate hasBeanParent() { exists(SpringBean b | b = this.getBeanParent()) } + predicate hasBeanParent() { exists(this.getBeanParent()) } predicate hasBeanAncestor(SpringBean ancestor) { ancestor = this.getBeanParent() or diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll index 2417002a412..3567f612fc5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringBeanFile.qll @@ -58,7 +58,7 @@ class SpringBeanFile extends XMLFile { /** Gets the `default-dependency-check` value for this file. */ string getDefaultDependencyCheck() { - if exists(XMLAttribute a | this.getBeansElement().getAttribute("default-dependency-check") = a) + if exists(this.getBeansElement().getAttribute("default-dependency-check")) then result = this.getBeansElement().getAttributeValue("default-dependency-check") else result = "none" } @@ -70,7 +70,7 @@ class SpringBeanFile extends XMLFile { /** Holds if this file has a `default-destroy-method` value. */ predicate hasDefaultDestroyMethod() { - exists(XMLAttribute a | this.getBeansElement().getAttribute("default-destroy-method") = a) + exists(this.getBeansElement().getAttribute("default-destroy-method")) } /** Gets the `default-init-method` value for this file. */ @@ -80,7 +80,7 @@ class SpringBeanFile extends XMLFile { /** Holds if the file has a `default-destroy-method` value. */ predicate hasDefaultInitMethod() { - exists(XMLAttribute a | this.getBeansElement().getAttribute("default-init-method") = a) + exists(this.getBeansElement().getAttribute("default-init-method")) } /** Holds if `default-lazy-init` is specified to be `true` for this file. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll index 837f7d06100..943285d99a8 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringXMLElement.qll @@ -18,7 +18,7 @@ class SpringXMLElement extends XMLElement { */ string getAttributeValueWithDefault(string attributeName) { this.hasAttribute(attributeName) and - if exists(XMLAttribute a | a = this.getAttribute(attributeName)) + if exists(this.getAttribute(attributeName)) then result = this.getAttributeValue(attributeName) else result = "default" } diff --git a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll index 35faa0e55ff..0f38147ad13 100644 --- a/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/struts/StrutsConventions.qll @@ -101,12 +101,7 @@ class Struts2ConventionActionClass extends Class { exists(string ancestorPackage | // Has an ancestor package on the whitelist ancestorPackage = this.getPackage().getName().splitAt(".") and - ( - ancestorPackage = "struts" or - ancestorPackage = "struts2" or - ancestorPackage = "action" or - ancestorPackage = "actions" - ) + ancestorPackage = ["struts", "struts2", "action", "actions"] ) and ( this.getName().matches("%" + getConventionSuffix(this)) or diff --git a/java/ql/lib/semmle/code/java/metrics/MetricElement.qll b/java/ql/lib/semmle/code/java/metrics/MetricElement.qll index 3a04fc7f205..086389e143c 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricElement.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricElement.qll @@ -43,11 +43,11 @@ class MetricElement extends Element { this.fromSource() and not this.getADependencySrc+() = this and ( - not exists(MetricElement t | t = this.getADependency()) and + not exists(this.getADependency()) and result = 0 or not this.getADependency().fromSource() and - exists(MetricElement e | this.getADependency() = e) and + exists(this.getADependency()) and result = 1 or result = this.getADependency().getALevel() + 1 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll b/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll index fb48d3d6dd7..b818c30edf6 100755 --- a/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll +++ b/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll @@ -18,7 +18,7 @@ class MetricStmt extends Stmt { /** Gets the nested depth of this statement. */ int getNestedDepth() { - not exists(Stmt s | s = this.getParent()) and result = 0 + not this.getParent() instanceof Stmt and result = 0 or exists(MetricStmt s | s = this.getParent() and result = s.getNestedDepth() + 1) } diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 8f4cef23ee6..01d73c031fc 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -34,6 +34,21 @@ class SSLSession extends RefType { SSLSession() { this.hasQualifiedName("javax.net.ssl", "SSLSession") } } +/** The `javax.net.ssl.SSLEngine` class. */ +class SSLEngine extends RefType { + SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } +} + +/** The `javax.net.ssl.SSLSocket` class. */ +class SSLSocket extends RefType { + SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } +} + +/** The `javax.net.ssl.SSLParameters` class. */ +class SSLParameters extends RefType { + SSLParameters() { this.hasQualifiedName("javax.net.ssl", "SSLParameters") } +} + class HostnameVerifier extends RefType { HostnameVerifier() { this.hasQualifiedName("javax.net.ssl", "HostnameVerifier") } } @@ -79,6 +94,14 @@ class GetSocketFactory extends Method { } } +/** The `createSSLEngine` method of the class `javax.net.ssl.SSLContext` */ +class CreateSslEngineMethod extends Method { + CreateSslEngineMethod() { + this.hasName("createSSLEngine") and + this.getDeclaringType() instanceof SSLContext + } +} + class SetConnectionFactoryMethod extends Method { SetConnectionFactoryMethod() { this.hasName("setSSLSocketFactory") and @@ -101,6 +124,38 @@ class SetDefaultHostnameVerifierMethod extends Method { } } +/** The `beginHandshake` method of the class `javax.net.ssl.SSLEngine`. */ +class BeginHandshakeMethod extends Method { + BeginHandshakeMethod() { + this.hasName("beginHandshake") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `wrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslWrapMethod extends Method { + SslWrapMethod() { + this.hasName("wrap") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `unwrap` method of the class `javax.net.ssl.SSLEngine`. */ +class SslUnwrapMethod extends Method { + SslUnwrapMethod() { + this.hasName("unwrap") and + this.getDeclaringType().getASupertype*() instanceof SSLEngine + } +} + +/** The `getSession` method of the class `javax.net.ssl.SSLSession`.select */ +class GetSslSessionMethod extends Method { + GetSslSessionMethod() { + this.hasName("getSession") and + this.getDeclaringType().getASupertype*() instanceof SSLSession + } +} + bindingset[algorithmString] private string algorithmRegex(string algorithmString) { // Algorithms usually appear in names surrounded by characters that are not diff --git a/java/ql/lib/semmle/code/java/security/FileWritable.qll b/java/ql/lib/semmle/code/java/security/FileWritable.qll index fbd359517e7..bd8329647da 100644 --- a/java/ql/lib/semmle/code/java/security/FileWritable.qll +++ b/java/ql/lib/semmle/code/java/security/FileWritable.qll @@ -62,7 +62,7 @@ private EnumConstant getAContainedEnumConstant(Expr enumSetRef) { private VarAccess getFileForPathConversion(Expr pathExpr) { pathExpr.getType().(RefType).hasQualifiedName("java.nio.file", "Path") and ( - // Look for conversion from `File` to `Path` using `file.getPath()`. + // Look for conversion from `File` to `Path` using `file.toPath()`. exists(MethodAccess fileToPath | fileToPath = pathExpr and result = fileToPath.getQualifier() and diff --git a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll index a325a5fd9b3..31f9e886e81 100644 --- a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll +++ b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll @@ -68,21 +68,7 @@ private class SendPendingIntent extends ImplicitPendingIntentSink { override predicate hasState(DataFlow::FlowState state) { state = "MutablePendingIntent" } } -/** - * Propagates taint from any tainted object to reads from its `PendingIntent`-typed fields. - */ -private class PendingIntentAsFieldAdditionalTaintStep extends ImplicitPendingIntentAdditionalTaintStep { - override predicate step(DataFlow::Node node1, DataFlow::Node node2) { - exists(Field f | - f.getType() instanceof PendingIntent and - node1.(DataFlow::PostUpdateNode).getPreUpdateNode() = - DataFlow::getFieldQualifier(f.getAnAccess().(FieldWrite)) and - node2.asExpr().(FieldRead).getField() = f - ) - } -} - -private class MutablePendingIntentFlowStep extends PendingIntentAsFieldAdditionalTaintStep { +private class MutablePendingIntentFlowStep extends ImplicitPendingIntentAdditionalTaintStep { override predicate step( DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, DataFlow::FlowState state2 diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll similarity index 60% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.ql rename to java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll index 598113ed5cd..3a9b80edc0f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.ql +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManager.qll @@ -1,28 +1,52 @@ -/** - * @name `TrustManager` that accepts all certificates - * @description Trusting all certificates allows an attacker to perform a machine-in-the-middle attack. - * @kind path-problem - * @problem.severity error - * @precision high - * @id java/insecure-trustmanager - * @tags security - * external/cwe/cwe-295 - */ +/** Provides classes and predicates to reason about insecure `TrustManager`s. */ import java -import semmle.code.java.controlflow.Guards -import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.security.Encryption -import semmle.code.java.security.SecurityFlag -import DataFlow::PathGraph +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.security.Encryption +private import semmle.code.java.security.SecurityFlag + +/** The creation of an insecure `TrustManager`. */ +abstract class InsecureTrustManagerSource extends DataFlow::Node { } + +private class DefaultInsecureTrustManagerSource extends InsecureTrustManagerSource { + DefaultInsecureTrustManagerSource() { + this.asExpr().(ClassInstanceExpr).getConstructedType() instanceof InsecureX509TrustManager + } +} + +/** + * The use of a `TrustManager` in an SSL context. + * Intentionally insecure connections are not considered sinks. + */ +abstract class InsecureTrustManagerSink extends DataFlow::Node { + InsecureTrustManagerSink() { not isGuardedByInsecureFlag(this) } +} + +private class DefaultInsecureTrustManagerSink extends InsecureTrustManagerSink { + DefaultInsecureTrustManagerSink() { + exists(MethodAccess ma, Method m | + m.hasName("init") and + m.getDeclaringType() instanceof SSLContext and + ma.getMethod() = m + | + ma.getArgument(1) = this.asExpr() + ) + } +} + +/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ +private predicate isGuardedByInsecureFlag(DataFlow::Node node) { + exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | + g = getASecurityFeatureFlagGuard() or g = getAnInsecureTrustManagerFlagGuard() + ) +} /** * An insecure `X509TrustManager`. * An `X509TrustManager` is considered insecure if it never throws a `CertificateException` * and therefore implicitly trusts any certificate as valid. */ -class InsecureX509TrustManager extends RefType { +private class InsecureX509TrustManager extends RefType { InsecureX509TrustManager() { this.getASupertype*() instanceof X509TrustManager and exists(Method m | @@ -59,27 +83,6 @@ private predicate mayThrowCertificateException(Method m) { ) } -/** - * A configuration to model the flow of an `InsecureX509TrustManager` to an `SSLContext.init` call. - */ -class InsecureTrustManagerConfiguration extends TaintTracking::Configuration { - InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } - - override predicate isSource(DataFlow::Node source) { - source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof InsecureX509TrustManager - } - - override predicate isSink(DataFlow::Node sink) { - exists(MethodAccess ma, Method m | - m.hasName("init") and - m.getDeclaringType() instanceof SSLContext and - ma.getMethod() = m - | - ma.getArgument(1) = sink.asExpr() - ) - } -} - /** * Flags suggesting a deliberately insecure `TrustManager` usage. */ @@ -98,20 +101,3 @@ private class InsecureTrustManagerFlag extends FlagKind { private Guard getAnInsecureTrustManagerFlagGuard() { result = any(InsecureTrustManagerFlag flag).getAFlag().asExpr() } - -/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */ -private predicate isNodeGuardedByFlag(DataFlow::Node node) { - exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | - g = getASecurityFeatureFlagGuard() or g = getAnInsecureTrustManagerFlagGuard() - ) -} - -from - DataFlow::PathNode source, DataFlow::PathNode sink, InsecureTrustManagerConfiguration cfg, - RefType trustManager -where - cfg.hasFlowPath(source, sink) and - not isNodeGuardedByFlag(sink.getNode()) and - trustManager = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() -select sink, source, sink, "$@ that is defined $@ and trusts any certificate, is used here.", - source, "This trustmanager", trustManager, "here" diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll new file mode 100644 index 00000000000..6c92570633d --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll @@ -0,0 +1,25 @@ +/** Provides taint tracking configurations to be used in Trust Manager queries. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.InsecureTrustManager + +/** + * A configuration to model the flow of an insecure `TrustManager` + * to the initialization of an SSL context. + */ +class InsecureTrustManagerConfiguration extends DataFlow::Configuration { + InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source instanceof InsecureTrustManagerSource + } + + override predicate isSink(DataFlow::Node sink) { sink instanceof InsecureTrustManagerSink } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) { + (this.isSink(node) or this.isAdditionalFlowStep(node, _)) and + node.getType() instanceof Array and + c instanceof DataFlow::ArrayContent + } +} diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll new file mode 100644 index 00000000000..8a51de7efd7 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -0,0 +1,146 @@ +/** + * Provides classes and predicates to reason about Intent URI permission manipulation + * vulnerabilities on Android. + */ + +import java +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.frameworks.android.Android +private import semmle.code.java.frameworks.android.Intent + +/** + * A sink for Intent URI permission manipulation vulnerabilities in Android, + * that is, method calls that return an Intent as the result of an Activity. + */ +abstract class IntentUriPermissionManipulationSink extends DataFlow::Node { } + +/** + * A sanitizer that makes sure that an Intent is safe to be returned to another Activity. + * + * Usually, this is done by setting the Intent's data URI and/or its flags to safe values. + */ +abstract class IntentUriPermissionManipulationSanitizer extends DataFlow::Node { } + +/** + * A guard that makes sure that an Intent is safe to be returned to another Activity. + * + * Usually, this is done by checking that the Intent's data URI and/or its flags contain + * expected values. + */ +abstract class IntentUriPermissionManipulationGuard extends DataFlow::BarrierGuard { } + +/** + * An additional taint step for flows related to Intent URI permission manipulation + * vulnerabilities. + */ +class IntentUriPermissionManipulationAdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for flows related to Intent URI permission manipulation vulnerabilities. + */ + abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); +} + +private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermissionManipulationSink { + DefaultIntentUriPermissionManipulationSink() { + exists(MethodAccess ma | ma.getMethod() instanceof ActivitySetResultMethod | + ma.getArgument(1) = this.asExpr() + ) + } +} + +/** + * Sanitizer that prevents access to arbitrary content providers by modifying the Intent in one of + * the following ways: + * * Removing the flags `FLAG_GRANT_READ_URI_PERMISSION` and `FLAG_GRANT_WRITE_URI_PERMISSION`. + * * Setting the flags to a combination that doesn't include `FLAG_GRANT_READ_URI_PERMISSION` or + * `FLAG_GRANT_WRITE_URI_PERMISSION`. + * * Replacing the data URI. + */ +private class IntentFlagsOrDataChangedSanitizer extends IntentUriPermissionManipulationSanitizer { + IntentFlagsOrDataChangedSanitizer() { + exists(MethodAccess ma, Method m | + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + this.asExpr() = ma.getQualifier() + | + m.hasName("removeFlags") and + bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantReadUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) and + bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantWriteUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) + or + m.hasName("setFlags") and + not bitwiseLocalTaintStep*(DataFlow::exprNode(any(GrantUriPermissionFlag f).getAnAccess()), + DataFlow::exprNode(ma.getArgument(0))) + or + m.hasName("setData") + ) + } +} + +/** + * A guard that checks an Intent's flags or data URI to make sure they are trusted. + * It matches the following patterns: + * + * ```java + * if (intent.getData().equals("trustedValue")) {} + * + * if (intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION == 0 && + * intent.getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION == 0) {} + * + * if (intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION != 0 || + * intent.getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0) {} + * ``` + */ +private class IntentFlagsOrDataCheckedGuard extends IntentUriPermissionManipulationGuard { + Expr condition; + + IntentFlagsOrDataCheckedGuard() { intentFlagsOrDataChecked(this, _, _) } + + override predicate checks(Expr e, boolean branch) { intentFlagsOrDataChecked(this, e, branch) } +} + +/** + * Holds if `g` checks `intent` when the result of an `intent.getFlags` or `intent.getData` call + * is equality-tested. + */ +private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch) { + exists(MethodAccess ma, Method m, Expr checkedValue | + ma.getQualifier() = intent and + ma.getMethod() = m and + m.getDeclaringType() instanceof TypeIntent and + m.hasName(["getFlags", "getData"]) and + bitwiseLocalTaintStep*(DataFlow::exprNode(ma), DataFlow::exprNode(checkedValue)) + | + bitwiseCheck(g, branch) and + checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr) + or + g.(MethodAccess).getMethod() instanceof EqualsMethod and + branch = true and + checkedValue = [g.(MethodAccess).getArgument(0), g.(MethodAccess).getQualifier()] + ) +} + +/** + * Holds if `g` is a bitwise check. `branch` is `true` when the expected value is `0` + * and `false` otherwise. + */ +private predicate bitwiseCheck(Guard g, boolean branch) { + exists(CompileTimeConstantExpr operand | operand = g.(EqualityTest).getAnOperand() | + if operand.getIntValue() = 0 + then g.(EqualityTest).polarity() = branch + else g.(EqualityTest).polarity().booleanNot() = branch + ) +} + +/** + * Holds if taint can flow from `source` to `sink` in one local step, + * including bitwise operations. + */ +private predicate bitwiseLocalTaintStep(DataFlow::Node source, DataFlow::Node sink) { + TaintTracking::localTaintStep(source, sink) or + source.asExpr() = sink.asExpr().(BitwiseExpr).(BinaryExpr).getAnOperand() +} diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll new file mode 100644 index 00000000000..067277a71b7 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -0,0 +1,34 @@ +/** + * Provides taint tracking configurations to be used in queries related to Intent URI permission + * manipulation in Android. + */ + +import java +private import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.DataFlow +private import IntentUriPermissionManipulation + +/** + * A taint tracking configuration for user-provided Intents being returned to third party apps. + */ +class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { + IntentUriPermissionManipulationConf() { this = "UriPermissionManipulationConf" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof IntentUriPermissionManipulationSink + } + + override predicate isSanitizer(DataFlow::Node barrier) { + barrier instanceof IntentUriPermissionManipulationSanitizer + } + + override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { + guard instanceof IntentUriPermissionManipulationGuard + } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + any(IntentUriPermissionManipulationAdditionalTaintStep c).step(node1, node2) + } +} diff --git a/java/ql/lib/semmle/code/java/security/JndiInjection.qll b/java/ql/lib/semmle/code/java/security/JndiInjection.qll index ebdf273d7d6..9dc0a86c502 100644 --- a/java/ql/lib/semmle/code/java/security/JndiInjection.qll +++ b/java/ql/lib/semmle/code/java/security/JndiInjection.qll @@ -88,7 +88,12 @@ private class DefaultJndiInjectionSinkModel extends SinkModelCsv { // Spring "org.springframework.jndi;JndiTemplate;false;lookup;;;Argument[0];jndi-injection", // spring-ldap 1.2.x and newer - "org.springframework.ldap.core;LdapOperations;true;lookup;;;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(Name);;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(Name,ContextMapper);;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(Name,String[],ContextMapper);;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(String);;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(String,ContextMapper);;Argument[0];jndi-injection", + "org.springframework.ldap.core;LdapOperations;true;lookup;(String,String[],ContextMapper);;Argument[0];jndi-injection", "org.springframework.ldap.core;LdapOperations;true;lookupContext;;;Argument[0];jndi-injection", "org.springframework.ldap.core;LdapOperations;true;findByDn;;;Argument[0];jndi-injection", "org.springframework.ldap.core;LdapOperations;true;rename;;;Argument[0];jndi-injection", diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll new file mode 100644 index 00000000000..c94864d8685 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrust.qll @@ -0,0 +1,98 @@ +/** Provides classes and predicates to reason about unsafe certificate trust vulnerablities. */ + +import java +private import semmle.code.java.frameworks.Networking +private import semmle.code.java.security.Encryption +private import semmle.code.java.dataflow.DataFlow + +/** + * The creation of an object that prepares an SSL connection. + * + * This is a source for `SslEndpointIdentificationFlowConfig`. + */ +class SslConnectionInit extends DataFlow::Node { + SslConnectionInit() { + exists(MethodAccess ma, Method m | + this.asExpr() = ma and + ma.getMethod() = m + | + m instanceof CreateSslEngineMethod + or + m instanceof CreateSocketMethod and isSslSocket(ma) + ) + } +} + +/** + * A call to a method that establishes an SSL connection. + * + * This is a sink for `SslEndpointIdentificationFlowConfig`. + */ +class SslConnectionCreation extends DataFlow::Node { + SslConnectionCreation() { + exists(MethodAccess ma, Method m | + m instanceof BeginHandshakeMethod or + m instanceof SslWrapMethod or + m instanceof SslUnwrapMethod or + m instanceof SocketGetOutputStreamMethod + | + ma.getMethod() = m and + this.asExpr() = ma.getQualifier() + ) + } +} + +/** + * An SSL object that correctly verifies hostnames, or doesn't need to (for instance, because it's a server). + * + * This is a sanitizer for `SslEndpointIdentificationFlowConfig`. + */ +abstract class SslUnsafeCertTrustSanitizer extends DataFlow::Node { } + +/** + * An `SSLEngine` set in server mode. + */ +private class SslEngineServerMode extends SslUnsafeCertTrustSanitizer { + SslEngineServerMode() { + exists(MethodAccess ma, Method m | + m.hasName("setUseClientMode") and + m.getDeclaringType().getASupertype*() instanceof SSLEngine and + ma.getMethod() = m and + ma.getArgument(0).(CompileTimeConstantExpr).getBooleanValue() = false and + this.asExpr() = ma.getQualifier() + ) + } +} + +/** + * Holds if the return value of `createSocket` is cast to `SSLSocket` + * or the qualifier of `createSocket` is an instance of `SSLSocketFactory`. + */ +private predicate isSslSocket(MethodAccess createSocket) { + createSocket = any(CastExpr ce | ce.getType() instanceof SSLSocket).getExpr() + or + createSocket.getQualifier().getType().(RefType).getASupertype*() instanceof SSLSocketFactory +} + +/** + * A call to a method that enables SSL (`useSslProtocol` or `setSslContextFactory`) + * on an instance of `com.rabbitmq.client.ConnectionFactory` that doesn't set `enableHostnameVerification`. + */ +class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { + RabbitMQEnableHostnameVerificationNotSet() { + this.getMethod().hasName(["useSslProtocol", "setSslContextFactory"]) and + this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and + exists(Variable v | + v.getType() instanceof RabbitMQConnectionFactory and + this.getQualifier() = v.getAnAccess() and + not exists(MethodAccess ma | + ma.getMethod().hasName("enableHostnameVerification") and + ma.getQualifier() = v.getAnAccess() + ) + ) + } +} + +private class RabbitMQConnectionFactory extends RefType { + RabbitMQConnectionFactory() { this.hasQualifiedName("com.rabbitmq.client", "ConnectionFactory") } +} diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll new file mode 100644 index 00000000000..767b86d4e41 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -0,0 +1,65 @@ +/** Provides taint tracking configurations to be used by unsafe certificate trust queries. */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.UnsafeCertTrust +import semmle.code.java.security.Encryption + +/** + * A taint flow configuration for SSL connections created without a proper certificate trust configuration. + */ +class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { + SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } + + override predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof SslUnsafeCertTrustSanitizer + } +} + +/** + * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. + */ +private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { + SslConnectionWithSafeSslParameters() { + exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer | + config.hasFlowTo(safe) and + sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and + DataFlow::localFlow(sanitizer, this) + ) + } +} + +private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { + SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } + + override predicate isSource(DataFlow::Node source) { + exists(MethodAccess ma | + ma instanceof SafeSetEndpointIdentificationAlgorithm and + DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode() + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma, RefType t | t instanceof SSLSocket or t instanceof SSLEngine | + ma.getMethod().hasName("setSSLParameters") and + ma.getMethod().getDeclaringType().getASupertype*() = t and + ma.getArgument(0) = sink.asExpr() + ) + } +} + +/** + * A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-empty parameter. + */ +private class SafeSetEndpointIdentificationAlgorithm extends MethodAccess { + SafeSetEndpointIdentificationAlgorithm() { + this.getMethod().hasName("setEndpointIdentificationAlgorithm") and + this.getMethod().getDeclaringType() instanceof SSLParameters and + not this.getArgument(0) instanceof NullLiteral and + not this.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "" + } +} diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 4152cb907ad..d86ab04b441 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -312,7 +312,7 @@ MethodAccess getASafeFlexjsonUseCall() { result.getArgument(0) instanceof NullLiteral or result.getMethod().getParameterType(0) instanceof FlexjsonObjectFactory and - exists(NullLiteral e | e = result.getAnArgument()) + result.getAnArgument() instanceof NullLiteral ) } diff --git a/java/ql/lib/semmle/code/xml/AndroidManifest.qll b/java/ql/lib/semmle/code/xml/AndroidManifest.qll index 234aacca967..81b3c44e62b 100644 --- a/java/ql/lib/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/lib/semmle/code/xml/AndroidManifest.qll @@ -74,6 +74,13 @@ class AndroidReceiverXmlElement extends AndroidComponentXmlElement { AndroidReceiverXmlElement() { this.getName() = "receiver" } } +/** + * An XML attribute with the `android:` prefix. + */ +class AndroidXmlAttribute extends XMLAttribute { + AndroidXmlAttribute() { this.getNamespace().getPrefix() = "android" } +} + /** * A `` element in an Android manifest file. */ @@ -91,6 +98,14 @@ class AndroidProviderXmlElement extends AndroidComponentXmlElement { this.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() and this.getAnAttribute().(AndroidPermissionXmlAttribute).isRead() } + + predicate grantsUriPermissions() { + exists(AndroidXmlAttribute attr | + this.getAnAttribute() = attr and + attr.getName() = "grantUriPermissions" and + attr.getValue() = "true" + ) + } } /** diff --git a/java/ql/lib/semmle/code/xml/XML.qll b/java/ql/lib/semmle/code/xml/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/java/ql/lib/semmle/code/xml/XML.qll +++ b/java/ql/lib/semmle/code/xml/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql b/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql index 65d6250b340..adf79da9ba8 100644 --- a/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql +++ b/java/ql/src/Architecture/Dependencies/UnusedMavenDependencyBinary.ql @@ -23,7 +23,7 @@ where source.getADependency() = d and // There is not a Pom file for the target of this dependency, so we assume that it was resolved by // a binary file in the local maven repository. - not exists(Pom target | target = d.getPom()) and + not exists(d.getPom()) and // In order to accurately identify whether this binary dependency is required, we must have identified // a Maven repository. If we have not found a repository, it's likely that it has a custom path of // which we are unaware, so do not report any problems. diff --git a/java/ql/src/DeadCode/DeadField.ql b/java/ql/src/DeadCode/DeadField.ql index 8981926833a..6a80e13e716 100644 --- a/java/ql/src/DeadCode/DeadField.ql +++ b/java/ql/src/DeadCode/DeadField.ql @@ -16,12 +16,9 @@ import semmle.code.java.deadcode.DeadCode from DeadField f, Element origin, string reason where not f.isInDeadScope() and - if exists(FieldRead read | read = f.getAnAccess()) + if f.getAnAccess() instanceof FieldRead then ( - if - exists(DeadRoot root | - root = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable()) - ) + if exists(getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable())) then ( origin = getADeadRoot(f.getAnAccess().(FieldRead).getEnclosingCallable()) and reason = " is only read from dead code originating at $@." diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql index 397a1c349d3..81d18d4b272 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.ql @@ -14,5 +14,5 @@ import java import semmle.code.java.frameworks.spring.Spring from SpringBean b -where exists(SpringConstructorArg carg | b.getASpringChild() = carg) +where b.getASpringChild() instanceof SpringConstructorArg select b, "Use setter injection instead of constructor injection." diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql index cc05679a15b..1d924dc9d6d 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.ql @@ -15,12 +15,12 @@ import semmle.code.java.frameworks.spring.Spring class SpringConstructorArgUseShortcut extends SpringConstructorArg { SpringConstructorArgUseShortcut() { not this.hasArgValueString() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasArgValueString() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } @@ -28,12 +28,12 @@ class SpringConstructorArgUseShortcut extends SpringConstructorArg { class SpringEntryUseShortcut extends SpringEntry { SpringEntryUseShortcut() { not this.hasValueStringRaw() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasValueStringRaw() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } @@ -41,12 +41,12 @@ class SpringEntryUseShortcut extends SpringEntry { class SpringPropertyUseShortcut extends SpringProperty { SpringPropertyUseShortcut() { not this.hasPropertyValueString() and - exists(SpringValue val | val = this.getASpringChild()) + this.getASpringChild() instanceof SpringValue } string getMessage() { not this.hasPropertyValueString() and - exists(SpringValue val | val = this.getASpringChild()) and + this.getASpringChild() instanceof SpringValue and result = "Use the shortcut \"value\" attribute instead of a nested element." } } diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql index f502d07440f..a18df356899 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql @@ -4,7 +4,6 @@ * guarantee an evenly distributed sequence of random numbers. * @kind problem * @problem.severity warning - * @security-severity 9.8 * @precision medium * @id java/random-used-once * @tags reliability diff --git a/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql b/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql index a23a8576f86..6d48a118e29 100644 --- a/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql +++ b/java/ql/src/Likely Bugs/Cloning/MissingMethodClone.ql @@ -16,7 +16,7 @@ from Class t, TypeCloneable cloneable where t.hasSupertype+(cloneable) and not t.isAbstract() and - not exists(CloneMethod m | t.getAMethod() = m) and + not t.getAMethod() instanceof CloneMethod and exists(Field f | f.getDeclaringType() = t and not f.isStatic()) and t.fromSource() select t, "No clone method, yet implements Cloneable." diff --git a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll index ea01b89deb3..d17f62cd76f 100644 --- a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll +++ b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.qll @@ -7,12 +7,7 @@ import semmle.code.java.dataflow.SSA * The kind of bound that is known to hold for some variable. */ library class BoundKind extends string { - BoundKind() { - this = "=" or - this = "!=" or - this = ">=" or - this = "<=" - } + BoundKind() { this = ["=", "!=", ">=", "<="] } predicate isEqual() { this = "=" } diff --git a/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql b/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql index d136d17dace..644c003a1dc 100644 --- a/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql +++ b/java/ql/src/Likely Bugs/Concurrency/WaitOutsideLoop.ql @@ -23,5 +23,5 @@ class WaitMethod extends Method { from MethodAccess ma where ma.getMethod() instanceof WaitMethod and - not exists(LoopStmt s | ma.getEnclosingStmt().getEnclosingStmt*() = s) + not ma.getEnclosingStmt().getEnclosingStmt*() instanceof LoopStmt select ma, "To avoid spurious wake-ups, 'wait' should only be called inside a loop." diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql index 59388163757..b651d1fcb82 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql @@ -21,5 +21,5 @@ where not f.isStatic() or not f.getType().hasName("long") ) and - exists(TypeSerializable serializable | f.getDeclaringType().getASupertype+() = serializable) + f.getDeclaringType().getASupertype+() instanceof TypeSerializable select f, "serialVersionUID should be final, static, and of type long." diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql index 5e31cb6ca8c..3a1a41add3d 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.ql @@ -14,7 +14,7 @@ import java import semmle.code.java.JDKAnnotations -predicate isSerializable(RefType t) { exists(TypeSerializable ts | ts = t.getASupertype*()) } +predicate isSerializable(RefType t) { t.getASupertype*() instanceof TypeSerializable } predicate withinStaticContext(NestedClass c) { c.isStatic() or diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java new file mode 100644 index 00000000000..4d53add78c2 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.java @@ -0,0 +1,25 @@ +public class IntentUriPermissionManipulation extends Activity { + + // BAD: the user-provided Intent is returned as-is + public void dangerous() { + Intent intent = getIntent(); + intent.putExtra("result", "resultData"); + setResult(intent); + } + + // GOOD: a new Intent is created and returned + public void safe() { + Intent intent = new Intent(); + intent.putExtra("result", "resultData"); + setResult(intent); + } + + // GOOD: the user-provided Intent is sanitized before being returned + public void sanitized() { + Intent intent = getIntent(); + intent.putExtra("result", "resultData"); + intent.removeFlags( + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + setResult(intent); + } +} diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp new file mode 100644 index 00000000000..5577cf7cdb8 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.qhelp @@ -0,0 +1,34 @@ + + + +

When an Android component expects a result from an Activity, startActivityForResult can be used. +The started Activity can then use setResult to return the appropriate data to the calling component.

+

If an Activity obtains the incoming, user-provided Intent and directly returns it via setResult +without any checks, the application may be unintentionally giving arbitrary access to its content providers, even +if they are not exported, as long as they are configured with the attribute android:grantUriPermissions="true". +This happens because the attacker adds the appropriate URI permission flags to the provided Intent, which take effect +once the Intent is reflected back.

+
+ + +

Avoid returning user-provided or untrusted Intents via setResult. Use a new Intent instead.

+

If it is required to use the received Intent, make sure that it does not contain URI permission flags, either +by checking them with Intent.getFlags or removing them with Intent.removeFlags.

+
+ + +

The following sample contains three examples. In the first example, a user-provided Intent is obtained and + directly returned back with setResult, which is dangerous. In the second example, a new Intent + is created to safely return the desired data. The third example shows how the obtained Intent can be sanitized + by removing dangerous flags before using it to return data to the calling component. +

+ + +
+ + +
  • Google Help: Remediation for Intent Redirection Vulnerability.
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql new file mode 100644 index 00000000000..b108da2f1de --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -0,0 +1,24 @@ +/** + * @name Intent URI permission manipulation + * @description Returning an externally provided Intent via 'setResult' may allow a malicious + * application to access arbitrary content providers of the vulnerable application. + * @kind path-problem + * @problem.severity error + * @security-severity 7.8 + * @precision high + * @id java/android/intent-uri-permission-manipulation + * @tags security + * external/cwe/cwe-266 + * external/cwe/cwe-926 + */ + +import java +import semmle.code.java.security.IntentUriPermissionManipulationQuery +import semmle.code.java.dataflow.DataFlow +import DataFlow::PathGraph + +from DataFlow::PathNode source, DataFlow::PathNode sink +where any(IntentUriPermissionManipulationConf c).hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "This Intent can be set with arbitrary flags from $@, " + + "and used to give access to internal content providers.", source.getNode(), "this user input" diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.java rename to java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.java diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp new file mode 100644 index 00000000000..8545b3ffbb6 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.qhelp @@ -0,0 +1,50 @@ + + + + +

    Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (the later is checked by the java/insecure-hostname-verifier query). The trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.

    +

    When SSLSocket or SSLEngine are created without a secure setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    +

    This query checks whether setEndpointIdentificationAlgorithm is missing, thereby making the application vulnerable to man-in-the-middle attacks. The query also covers insecure configurations of com.rabbitmq.client.ConnectionFactory.

    +
    + + +

    Validate SSL certificates in SSL authentication.

    +
    + + +

    The following two examples show two ways of configuring SSLSocket/SSLEngine. In the 'BAD' case, +setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the 'GOOD' case, setEndpointIdentificationAlgorithm is called.

    + +
    + + +
  • +Testing Endpoint Identify Verification (MSTG-NETWORK-3). +
  • +
  • + SSLParameters.setEndpointIdentificationAlgorithm documentation. +
  • +
  • + RabbitMQ: + ConnectionFactory.enableHostnameVerification documentation. +
  • +
  • + RabbitMQ: + Using TLS in the Java Client. +
  • +
  • +CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification. +
  • +
  • +CVE-2018-8034: Apache Tomcat - host name verification when using TLS with the WebSocket client. +
  • +
  • +CVE-2018-11087: Pivotal Spring AMQP vulnerability due to lack of hostname validation. +
  • +
  • +CVE-2018-11775: TLS hostname verification issue when using the Apache ActiveMQ Client. +
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql new file mode 100644 index 00000000000..13e1375d164 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -0,0 +1,23 @@ +/** + * @name Unsafe certificate trust + * @description SSLSocket/SSLEngine ignores all SSL certificate validation + * errors when establishing an HTTPS connection, thereby making + * the app vulnerable to man-in-the-middle attacks. + * @kind problem + * @problem.severity warning + * @precision medium + * @id java/unsafe-cert-trust + * @tags security + * external/cwe/cwe-273 + */ + +import java +import semmle.code.java.security.UnsafeCertTrustQuery + +from Expr unsafeTrust +where + unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or + exists(SslEndpointIdentificationFlowConfig config | + config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) + ) +select unsafeTrust, "Unsafe configuration of trusted certificates." diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.java b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.java rename to java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.qhelp b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp similarity index 86% rename from java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.qhelp rename to java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp index 99746477a34..349c7640b5f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-295/InsecureTrustManager.qhelp +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.qhelp @@ -4,8 +4,8 @@

    -If the checkServerTrusted method of a TrustManager never throws a CertificateException it trusts every certificate. -This allows an attacker to perform a machine-in-the-middle attack against the application therefore breaking any security Transport Layer Security (TLS) gives. +If the checkServerTrusted method of a TrustManager never throws a CertificateException, it trusts every certificate. +This allows an attacker to perform a machine-in-the-middle attack against the application, therefore breaking any security Transport Layer Security (TLS) gives.

    @@ -42,6 +42,6 @@ is loaded into a KeyStore. This explicitly defines the certificate -

  • Android Develoers:Security with HTTPS and SSL.
  • +
  • Android Developers: Security with HTTPS and SSL.
  • diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql new file mode 100644 index 00000000000..bb3fc7bfb49 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql @@ -0,0 +1,21 @@ +/** + * @name `TrustManager` that accepts all certificates + * @description Trusting all certificates allows an attacker to perform a machine-in-the-middle attack. + * @kind path-problem + * @problem.severity error + * @security-severity 7.5 + * @precision high + * @id java/insecure-trustmanager + * @tags security + * external/cwe/cwe-295 + */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.security.InsecureTrustManagerQuery +import DataFlow::PathGraph + +from DataFlow::PathNode source, DataFlow::PathNode sink +where any(InsecureTrustManagerConfiguration cfg).hasFlowPath(source, sink) +select sink, source, sink, "This $@, which is defined $@ and trusts any certificate, is used here.", + source, "TrustManager", source.getNode().asExpr().(ClassInstanceExpr).getConstructedType(), "here" diff --git a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp index 5fd407b93ae..44c3c6d9a92 100644 --- a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp +++ b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.qhelp @@ -5,42 +5,42 @@ -

    A PendingIntent describes an action in the form of an Intent that is intended to be given and executed - at a later time by another application. The Intent wrapped by a PendingIntent is executed on behalf of - the application that created it, and with its same privileges.

    -

    If a PendingIntent is configured to be mutable, the fields of its internal Intent can be changed by the - receiving application if they were not previously set. This means that a mutable PendingIntent that has - not defined a destination component (that is, an implicit PendingIntent) can be altered to execute an +

    A PendingIntent is used to wrap an Intent that will be supplied and executed by another + application. When the Intent is executed, it behaves as if it were run directly by the supplying + application, using the privileges of that application.

    +

    If a PendingIntent is configured to be mutable, the fields of its internal Intent can be changed by the + receiving application if they were not previously set. This means that a mutable PendingIntent that has + not defined a destination component (that is, an implicit PendingIntent) can be altered to execute an arbitrary action with the privileges of the application that created it.

    -

    If an implicit PendingIntent is obtainable by a malicious application by any of the following means:

    +

    A malicious application can access an implicit PendingIntent as follows:

      -
    • It is wrapped and sent as an extra of another implicit Intent
    • -
    • It is sent as the action of a Slide
    • -
    • It is sent as the action of a Notification
    • +
    • It is wrapped and sent as an extra of another implicit Intent.
    • +
    • It is sent as the action of a Slide.
    • +
    • It is sent as the action of a Notification.

    -

    the attacker could modify the underlying Intent and execute an arbitrary action with elevated privileges. - This could give the malicious application access to private components of the victim application, - or the ability to perform actions without having the necessary permissions.

    +

    On gaining access, the attacker can modify the underlying Intent and execute an arbitrary action + with elevated privileges. This could give the malicious application access to private components of the victim + application, or the ability to perform actions without having the necessary permissions.

    -

    Avoid creating implicit PendingIntents. This means that the underlying Intent should always have an +

    Avoid creating implicit PendingIntents. This means that the underlying Intent should always have an explicit destination component.

    -

    Also, when adding the PendingIntent as an extra of another Intent, make sure that said Intent also has +

    When you add the PendingIntent as an extra of another Intent, make sure that this second Intent also has an explicit destination component, so that it is not delivered to untrusted applications.

    -

    It is also recommended to create the PendingIntent using the flag FLAG_IMMUTABLE whenever - possible, to prevent the destination component from modifying empty fields of the underlying Intent.

    +

    Create the PendingIntent using the flag FLAG_IMMUTABLE whenever possible, + to prevent the destination component from modifying empty fields of the underlying Intent.

    -

    In the following examples, a PendingIntent is created and wrapped as an extra of another Intent. +

    In the following examples, a PendingIntent is created and wrapped as an extra of another Intent.

    -

    In the first example, both the PendingIntent and the Intent it is wrapped in are implicit, - reproducing the vulnerability.

    +

    In the first example, both the PendingIntent and the Intent it is wrapped in are implicit, + making them vulnerable to attack.

    In the second example, the issue is avoided by adding explicit destination components to the - PendingIntent and the wrapping Intent.

    -

    The third example uses the FLAG_IMMUTABLE flag to prevent the underlying Intent from being modified + PendingIntent and the wrapping Intent.

    +

    The third example uses the FLAG_IMMUTABLE flag to prevent the underlying Intent from being modified by the destination component.

    diff --git a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql index e6aff45524d..4d8056f68cd 100644 --- a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql +++ b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql @@ -1,8 +1,8 @@ /** * @name Use of implicit PendingIntents - * @description Implicit and mutable PendingIntents being sent to an unspecified third party - * component may provide access to internal components of the application or cause - * other unintended effects. + * @description Sending an implicit and mutable 'PendingIntent' to an unspecified third party + * component may provide an attacker with access to internal components of the + * application or cause other unintended effects. * @kind path-problem * @problem.severity error * @security-severity 8.2 diff --git a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql index 6dd0fa2fcac..33fe1cdb46d 100644 --- a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql +++ b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql @@ -16,7 +16,7 @@ predicate nonEmptyArrayLiteralOrNull(Expr e) { exists(ArrayCreationExpr arr | arr = e | // Array initializer expressions such as `{1, 2, 3}`. // Array is empty if the initializer expression is empty. - exists(Expr arrayValue | arrayValue = arr.getInit().getAnInit()) + exists(arr.getInit().getAnInit()) or // Array creation with dimensions (but without initializers). // Empty if the first dimension is 0. diff --git a/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md new file mode 100644 index 00000000000..bde0c9d0249 --- /dev/null +++ b/java/ql/src/change-notes/2021-06-28-unsafe-cert-trust-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query "Unsafe certificate trust" (`java/unsafe-cert-trust`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3550). diff --git a/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md new file mode 100644 index 00000000000..fddecd1b953 --- /dev/null +++ b/java/ql/src/change-notes/2021-10-27-android-intent-uri-permission-manipulation-query.md @@ -0,0 +1,6 @@ +--- +category: newQuery +--- +* A new query "Intent URI permission manipulation" (`java/android/intent-uri-permission-manipulation`) has been added. +This query finds Android components that return unmodified, received Intents to the calling applications, which +can provide unintended access to internal content providers of the victim application. \ No newline at end of file diff --git a/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md b/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md new file mode 100644 index 00000000000..7789ebe3c25 --- /dev/null +++ b/java/ql/src/change-notes/2021-11-15-insecure-trustamanger-query.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query "`TrustManager` that accepts all certificates" (`java/insecure-trustmanager`) has been promoted from experimental to the main query pack. Its results will now appear by default. This query was originally [submitted as an experimental query by @intrigus-lgtm](https://github.com/github/codeql/pull/4879). diff --git a/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md b/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md index a752d5c5ccd..8549f3863a6 100644 --- a/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md +++ b/java/ql/src/change-notes/2021-12-21-android-implicit-pendingintents.md @@ -2,6 +2,6 @@ category: newQuery --- * A new query "Use of implicit PendingIntents" (`java/android/pending-intents`) has been added. -This query finds implicit and mutable `PendingIntents` being sent to an unspecified third party component, -which can provide access to internal components of the application or cause other unintended -effects. \ No newline at end of file +This query finds implicit and mutable `PendingIntents` sent to an unspecified third party +component, which may provide an attacker with access to internal components of the application +or cause other unintended effects. \ No newline at end of file diff --git a/java/ql/src/change-notes/2022-01-19-random-used-once.md b/java/ql/src/change-notes/2022-01-19-random-used-once.md new file mode 100644 index 00000000000..f9a00c6528f --- /dev/null +++ b/java/ql/src/change-notes/2022-01-19-random-used-once.md @@ -0,0 +1,4 @@ +--- +category: queryMetadata +--- +* The "Random used only once" (`java/random-used-once`) query no longer has a `security-severity` score. This has been causing some tools to categorise it as a security query, when it is more useful as a code-quality query. diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql index e4ec03ed956..69175790af7 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringImplicitViewManipulation.ql @@ -58,7 +58,7 @@ where not m.getParameterType(_) instanceof HttpServletResponse and // A spring request mapping method which does not have response body annotation applied to it m.getAnAnnotation().getType() instanceof SpringRequestMappingAnnotationType and - not exists(SpringResponseBodyAnnotationType t | t = m.getAnAnnotation().getType()) and + not m.getAnAnnotation().getType() instanceof SpringResponseBodyAnnotationType and // `@RestController` inherits `@ResponseBody` internally so it should be ignored. not m.getDeclaringType() instanceof SpringRestController select m, "This method may be vulnerable to spring view manipulation vulnerabilities" diff --git a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll index 9a2a0b9d3d1..a68cfb9fd64 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-200/AndroidFileIntentSource.qll @@ -32,9 +32,7 @@ class GetContentIntent extends ClassInstanceExpr { class GetContentIntentConfig extends TaintTracking2::Configuration { GetContentIntentConfig() { this = "GetContentIntentConfig" } - override predicate isSource(DataFlow2::Node src) { - exists(GetContentIntent gi | src.asExpr() = gi) - } + override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof GetContentIntent } override predicate isSink(DataFlow2::Node sink) { exists(MethodAccess ma | diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp deleted file mode 100644 index ae8d76b1bb1..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.qhelp +++ /dev/null @@ -1,42 +0,0 @@ - - - - -

    When SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.

    -

    Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.

    -

    This query checks whether setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.

    -
    - - -

    Validate SSL certificate in SSL authentication.

    -
    - - -

    The following two examples show two ways of configuring SSLSocket/SSLEngine. In the 'BAD' case, -setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the 'GOOD' case, setEndpointIdentificationAlgorithm is called.

    - -
    - - -
  • -CWE-273 -
  • -
  • -Testing Endpoint Identify Verification (MSTG-NETWORK-3) -
  • -
  • -CVE-2018-17187: Apache Qpid Proton-J transport issue with hostname verification -
  • -
  • -CVE-2018-8034: Apache Tomcat - host name verification when using TLS with the WebSocket client -
  • -
  • -CVE-2018-11087: Pivotal Spring AMQP vulnerability due to lack of hostname validation -
  • -
  • -CVE-2018-11775: TLS hostname verification issue when using the Apache ActiveMQ Client -
  • -
    -
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql deleted file mode 100644 index a86505606ca..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @name Unsafe certificate trust - * @description SSLSocket/SSLEngine ignores all SSL certificate validation - * errors when establishing an HTTPS connection, thereby making - * the app vulnerable to man-in-the-middle attacks. - * @kind problem - * @problem.severity warning - * @precision medium - * @id java/unsafe-cert-trust - * @tags security - * external/cwe/cwe-273 - */ - -import java -import semmle.code.java.security.Encryption - -class SSLEngine extends RefType { - SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") } -} - -class Socket extends RefType { - Socket() { this.hasQualifiedName("java.net", "Socket") } -} - -class SocketFactory extends RefType { - SocketFactory() { this.hasQualifiedName("javax.net", "SocketFactory") } -} - -class SSLSocket extends RefType { - SSLSocket() { this.hasQualifiedName("javax.net.ssl", "SSLSocket") } -} - -/** - * has setEndpointIdentificationAlgorithm set correctly - */ -predicate setEndpointIdentificationAlgorithm(MethodAccess createSSL) { - exists( - Variable sslo, MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set - | - createSSL = sslo.getAnAssignedValue() and - ma.getQualifier() = sslo.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") and - ma.getArgument(0) = sslparams.getAnAccess() and - exists(MethodAccess setepa | - setepa.getQualifier() = sslparams.getAnAccess() and - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and - not setepa.getArgument(0) instanceof NullLiteral - ) - ) -} - -/** - * has setEndpointIdentificationAlgorithm set correctly - */ -predicate hasEndpointIdentificationAlgorithm(Variable ssl) { - exists( - MethodAccess ma, Variable sslparams //setSSLParameters with valid setEndpointIdentificationAlgorithm set - | - ma.getQualifier() = ssl.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") and - ma.getArgument(0) = sslparams.getAnAccess() and - exists(MethodAccess setepa | - setepa.getQualifier() = sslparams.getAnAccess() and - setepa.getMethod().hasName("setEndpointIdentificationAlgorithm") and - not setepa.getArgument(0) instanceof NullLiteral - ) - ) -} - -/** - * Cast of Socket to SSLSocket - */ -predicate sslCast(MethodAccess createSSL) { - exists(Variable ssl, CastExpr ce | - ce.getExpr() = createSSL and - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and - ssl.getType() instanceof SSLSocket //With a type cast `SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443)` - ) -} - -/** - * SSL object is created in a separate method call or in the same method - */ -predicate hasFlowPath(MethodAccess createSSL, Variable ssl) { - ( - createSSL = ssl.getAnAssignedValue() - or - exists(CastExpr ce | - ce.getExpr() = createSSL and - ce.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl //With a type cast like SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); - ) - ) - or - exists(MethodAccess tranm | - createSSL.getEnclosingCallable() = tranm.getMethod() and - tranm.getControlFlowNode().getASuccessor().(VariableAssign).getDestVar() = ssl and - not setEndpointIdentificationAlgorithm(createSSL) //Check the scenario of invocation before used in the current method - ) -} - -/** - * Not have the SSLParameter set - */ -predicate hasNoEndpointIdentificationSet(MethodAccess createSSL, Variable ssl) { - //No setSSLParameters set - hasFlowPath(createSSL, ssl) and - not exists(MethodAccess ma | - ma.getQualifier() = ssl.getAnAccess() and - ma.getMethod().hasName("setSSLParameters") - ) - or - //No endpointIdentificationAlgorithm set with setSSLParameters - hasFlowPath(createSSL, ssl) and - not setEndpointIdentificationAlgorithm(createSSL) -} - -/** - * The setEndpointIdentificationAlgorithm method of SSLParameters with the ssl engine or socket - */ -class SSLEndpointIdentificationNotSet extends MethodAccess { - SSLEndpointIdentificationNotSet() { - ( - this.getMethod().hasName("createSSLEngine") and - this.getMethod().getDeclaringType() instanceof SSLContext //createEngine method of SSLContext - or - this.getMethod().hasName("createSocket") and - this.getMethod().getDeclaringType() instanceof SocketFactory and - this.getMethod().getReturnType() instanceof Socket and - sslCast(this) //createSocket method of SocketFactory - ) and - exists(Variable ssl | - hasNoEndpointIdentificationSet(this, ssl) and //Not set in itself - not exists(VariableAssign ar, Variable newSsl | - ar.getSource() = this.getCaller().getAReference() and - ar.getDestVar() = newSsl and - hasEndpointIdentificationAlgorithm(newSsl) //Not set in its caller either - ) - ) and - not exists(MethodAccess ma | ma.getMethod() instanceof HostnameVerifierVerify) //Reduce false positives since this method access set default hostname verifier - } -} - -class RabbitMQConnectionFactory extends RefType { - RabbitMQConnectionFactory() { this.hasQualifiedName("com.rabbitmq.client", "ConnectionFactory") } -} - -/** - * The com.rabbitmq.client.ConnectionFactory useSslProtocol method access without enableHostnameVerification - */ -class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess { - RabbitMQEnableHostnameVerificationNotSet() { - this.getMethod().hasName("useSslProtocol") and - this.getMethod().getDeclaringType() instanceof RabbitMQConnectionFactory and - exists(Variable v | - v.getType() instanceof RabbitMQConnectionFactory and - this.getQualifier() = v.getAnAccess() and - not exists(MethodAccess ma | - ma.getMethod().hasName("enableHostnameVerification") and - ma.getQualifier() = v.getAnAccess() - ) - ) - } -} - -from MethodAccess aa -where - aa instanceof SSLEndpointIdentificationNotSet or - aa instanceof RabbitMQEnableHostnameVerificationNotSet -select aa, "Unsafe configuration of trusted certificates" diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index 3120d25ea11..f917936a33f 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -52,7 +52,7 @@ class KeyGeneratorInitConfiguration extends TaintTracking::Configuration { KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { - exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr()) + source.asExpr() instanceof JavaxCryptoKeyGenerator } override predicate isSink(DataFlow::Node sink) { @@ -68,7 +68,7 @@ class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration { KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" } override predicate isSource(DataFlow::Node source) { - exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr()) + source.asExpr() instanceof JavaSecurityKeyPairGenerator } override predicate isSink(DataFlow::Node sink) { diff --git a/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll b/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll index bfa2530b07e..7ca794220fb 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-327/SslLib.qll @@ -94,18 +94,6 @@ class UnsafeTlsVersion extends StringLiteral { } } -class SSLParameters extends RefType { - SSLParameters() { hasQualifiedName("javax.net.ssl", "SSLParameters") } -} - -class SSLSocket extends RefType { - SSLSocket() { hasQualifiedName("javax.net.ssl", "SSLSocket") } -} - class SSLServerSocket extends RefType { SSLServerSocket() { hasQualifiedName("javax.net.ssl", "SSLServerSocket") } } - -class SSLEngine extends RefType { - SSLEngine() { hasQualifiedName("javax.net.ssl", "SSLEngine") } -} diff --git a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll b/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll index 5f4d85fe22b..5eff757a93d 100644 --- a/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll +++ b/java/ql/src/semmle/code/xml/MyBatisMapperXML.qll @@ -112,5 +112,5 @@ class MyBatisMapperInclude extends MyBatisMapperXMLElement { * A `` element in a `MyBatisMapperXMLElement`. */ class MyBatisMapperForeach extends MyBatisMapperXMLElement { - MyBatisMapperForeach() { getName() = "foreach" } + MyBatisMapperForeach() { this.getName() = "foreach" } } diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql index 69b4cf23acc..aab52da3058 100644 --- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql @@ -48,6 +48,7 @@ string captureSink(TargetAPI api) { config.hasFlow(src, sink) and sinkNode(sink, kind) and api = src.getEnclosingCallable() and + not kind = "logging" and result = asSinkModel(api, asInputArgument(src), kind) ) } diff --git a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql index 91767270c75..eb3ee0f8f53 100644 --- a/java/ql/src/utils/model-generator/CaptureSummaryModels.ql +++ b/java/ql/src/utils/model-generator/CaptureSummaryModels.ql @@ -223,7 +223,7 @@ string captureParameterToParameterFlow(TargetAPI api) { | result = asTaintModel(api, parameterAccess(source.asParameter()), - parameterAccess(sink.getPreUpdateNode().asExpr().(VarAccess).getVariable().(Parameter))) + parameterAccess(sink.getPreUpdateNode().asExpr().(VarAccess).getVariable())) ) } diff --git a/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll b/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll index f2f505e1af1..80f5292c740 100644 --- a/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll +++ b/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll @@ -29,7 +29,8 @@ private string isExtensible(RefType ref) { predicate isRelevantForModels(Callable api) { not isInTestFile(api.getCompilationUnit().getFile()) and - not isJdkInternal(api.getCompilationUnit()) + not isJdkInternal(api.getCompilationUnit()) and + not api instanceof MainMethod } private predicate isInTestFile(File file) { diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected deleted file mode 100644 index f26706a56d2..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.expected +++ /dev/null @@ -1,3 +0,0 @@ -| UnsafeCertTrustTest.java:26:25:26:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:37:25:37:52 | createSSLEngine(...) | Unsafe configuration of trusted certificates | -| UnsafeCertTrustTest.java:46:34:46:83 | createSocket(...) | Unsafe configuration of trusted certificates | diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref deleted file mode 100644 index f054d603787..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrust.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-273/UnsafeCertTrust.ql diff --git a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java deleted file mode 100644 index cb8b472eb8f..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-273/UnsafeCertTrustTest.java +++ /dev/null @@ -1,64 +0,0 @@ -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import java.net.Socket; -import javax.net.SocketFactory; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -//import com.rabbitmq.client.ConnectionFactory; - -public class UnsafeCertTrustTest { - - /** - * Test the endpoint identification of SSL engine is set to null - */ - public void testSSLEngineEndpointIdSetNull() throws java.security.NoSuchAlgorithmException { - SSLContext sslContext = SSLContext.getInstance("TLS"); - SSLEngine sslEngine = sslContext.createSSLEngine(); - SSLParameters sslParameters = sslEngine.getSSLParameters(); - sslParameters.setEndpointIdentificationAlgorithm(null); - sslEngine.setSSLParameters(sslParameters); - } - - /** - * Test the endpoint identification of SSL engine is not set - */ - public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException { - SSLContext sslContext = SSLContext.getInstance("TLS"); - SSLEngine sslEngine = sslContext.createSSLEngine(); - } - - /** - * Test the endpoint identification of SSL socket is not set - */ - public void testSSLSocketEndpointIdNotSet() throws java.security.NoSuchAlgorithmException, java.io.IOException { - SSLContext sslContext = SSLContext.getInstance("TLS"); - final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); - SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443); - } - - /** - * Test the endpoint identification of regular socket is not set - */ - public void testSocketEndpointIdNotSet() throws java.io.IOException { - SocketFactory socketFactory = SocketFactory.getDefault(); - Socket socket = socketFactory.createSocket("www.example.com", 80); - } - - // /** - // * Test the enableHostnameVerification of RabbitMQConnectionFactory is not set - // */ - // public void testEnableHostnameVerificationOfRabbitMQFactoryNotSet() { - // ConnectionFactory connectionFactory = new ConnectionFactory(); - // connectionFactory.useSslProtocol(); - // } -} diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected b/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected deleted file mode 100644 index 964c65889d4..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.expected +++ /dev/null @@ -1,109 +0,0 @@ -edges -| InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | -| InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:131:23:131:34 | trustManager | -| InsecureTrustManagerTest.java:130:55:130:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | -| InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:173:23:173:34 | trustManager | -| InsecureTrustManagerTest.java:172:55:172:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | -| InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:215:23:215:34 | trustManager | -| InsecureTrustManagerTest.java:214:55:214:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | -| InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | -| InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | -| InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | -| InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | -| InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | -| InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | -| InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | -| InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | -| InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | -| InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | -| InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | -| InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | -nodes -| InsecureTrustManagerTest.java:121:33:121:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:130:34:130:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:130:55:130:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:131:23:131:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:151:34:151:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:172:34:172:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:172:55:172:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:173:23:173:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:193:34:193:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:214:34:214:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:214:55:214:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:215:23:215:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:235:34:235:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:257:34:257:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:280:34:280:82 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:305:33:305:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:319:33:319:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:333:33:333:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:347:33:347:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:361:33:361:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:375:33:375:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:390:33:390:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:405:33:405:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | semmle.label | trustManager | -| InsecureTrustManagerTest.java:414:33:414:81 | {...} [[]] : InsecureTrustManager | semmle.label | {...} [[]] : InsecureTrustManager | -| InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | semmle.label | new InsecureTrustManager(...) : InsecureTrustManager | -| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | semmle.label | trustManager | -subpaths -#select -| InsecureTrustManagerTest.java:122:22:122:33 | trustManager | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:122:22:122:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:121:54:121:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:152:23:152:34 | trustManager | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:152:23:152:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:151:55:151:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:194:23:194:34 | trustManager | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:194:23:194:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:193:55:193:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:236:23:236:34 | trustManager | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:236:23:236:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:235:55:235:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:258:23:258:34 | trustManager | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:258:23:258:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:257:55:257:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:281:23:281:34 | trustManager | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:281:23:281:34 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:280:55:280:80 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:306:22:306:33 | trustManager | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:306:22:306:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:305:54:305:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:320:22:320:33 | trustManager | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:320:22:320:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:319:54:319:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:334:22:334:33 | trustManager | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:334:22:334:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:333:54:333:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:348:22:348:33 | trustManager | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:348:22:348:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:347:54:347:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:362:22:362:33 | trustManager | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:362:22:362:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:361:54:361:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:376:22:376:33 | trustManager | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:376:22:376:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:375:54:375:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:391:22:391:33 | trustManager | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:391:22:391:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:390:54:390:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:406:22:406:33 | trustManager | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:406:22:406:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:405:54:405:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | -| InsecureTrustManagerTest.java:415:22:415:33 | trustManager | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | InsecureTrustManagerTest.java:415:22:415:33 | trustManager | $@ that is defined $@ and trusts any certificate, is used here. | InsecureTrustManagerTest.java:414:54:414:79 | new InsecureTrustManager(...) : InsecureTrustManager | This trustmanager | InsecureTrustManagerTest.java:35:23:35:42 | InsecureTrustManager | here | diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref b/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref deleted file mode 100644 index 9950f627659..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManager.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-295/InsecureTrustManager.ql diff --git a/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java b/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java index c61ad642b88..0ef6f8f8e32 100644 --- a/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java +++ b/java/ql/test/library-tests/frameworks/android/content-provider/Safe.java @@ -11,7 +11,7 @@ import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -// This Content Provider isn't exported, so there shouldn't be any flow +// This content provider isn't exported, so there shouldn't be any flow public class Safe extends ContentProvider { void sink(Object o) {} diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql new file mode 100644 index 00000000000..e8c498bebdf --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql @@ -0,0 +1,11 @@ +import java +import semmle.code.java.dataflow.FlowSources +import TestUtilities.InlineFlowTest + +class SourceValueFlowConf extends DefaultValueFlowConf { + override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } +} + +class SourceInlineFlowTest extends InlineFlowTest { + override DataFlow::Configuration getTaintFlowConfig() { none() } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/Safe.java b/java/ql/test/library-tests/frameworks/android/sources/Safe.java new file mode 100644 index 00000000000..7a213f5edb0 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/Safe.java @@ -0,0 +1,21 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class Safe extends Activity { + + void sink(Object o) {} + + public void onCreate(Bundle saved) { + Intent explicitIntent = new Intent(this, Activity.class); + startActivityForResult(explicitIntent, 0); + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // Safe + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/Safe2.java b/java/ql/test/library-tests/frameworks/android/sources/Safe2.java new file mode 100644 index 00000000000..9a2e4a6074f --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/Safe2.java @@ -0,0 +1,20 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class Safe2 extends Activity { + + void sink(Object o) {} + + public void onCreate(Bundle saved) { + // activityForResult not called + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // Safe + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/Test.java b/java/ql/test/library-tests/frameworks/android/sources/Test.java new file mode 100644 index 00000000000..ee694ef7697 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/Test.java @@ -0,0 +1,21 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +public class Test extends Activity { + + void sink(Object o) {} + + public void onCreate(Bundle saved) { + Intent implicitIntent = new Intent("SOME_ACTION"); + startActivityForResult(implicitIntent, 0); + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // $ hasValueFlow + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java b/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java new file mode 100644 index 00000000000..bfa657c6d00 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java @@ -0,0 +1,32 @@ +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.os.Bundle; +import androidx.fragment.app.FragmentTransaction; + +public class TestActivityAndFragment extends Activity { + + private TestFragment frag; + + void sink(Object o) {} + + public void onCreate(Bundle saved) { + FragmentTransaction ft = null; + ft.add(0, frag); + + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // $ hasValueFlow + } + + private class TestFragment extends Fragment { + public void onCreate(Bundle savedInstance) { + Intent implicitIntent = new Intent("SOME_ACTION"); + startActivityForResult(implicitIntent, 0); + } + + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java b/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java new file mode 100644 index 00000000000..a2073f9b781 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java @@ -0,0 +1,22 @@ +package com.example.app; + +import android.app.Fragment; +import android.content.Intent; +import android.os.Bundle; + +public class TestFragment extends Fragment { + + void sink(Object o) {} + + public void onCreate(Bundle savedInstance) { + Intent implicitIntent = new Intent("SOME_ACTION"); + startActivityForResult(implicitIntent, 0); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // $ hasValueFlow + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java b/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java new file mode 100644 index 00000000000..4dbbfd9ca24 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java @@ -0,0 +1,28 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +public class TestMissing extends Activity { + + void sink(Object o) {} + + public void onCreate(Bundle saved) { + Helper.startNewActivity(this); + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + sink(requestCode); // safe + sink(resultCode); // safe + sink(data); // $ MISSING: $hasValueFlow + } + + static class Helper { + public static void startNewActivity(Activity ctx) { + Intent implicitIntent = new Intent("SOME_ACTION"); + ctx.startActivityForResult(implicitIntent, 0); + } + } +} diff --git a/java/ql/test/library-tests/frameworks/android/sources/options b/java/ql/test/library-tests/frameworks/android/sources/options new file mode 100644 index 00000000000..33cdc1ea940 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/sources/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/Nullness/B.java b/java/ql/test/query-tests/Nullness/B.java index 193d61e497f..0ab6d58dbae 100644 --- a/java/ql/test/query-tests/Nullness/B.java +++ b/java/ql/test/query-tests/Nullness/B.java @@ -371,4 +371,41 @@ public class B { } } + public void bitwise(Object x, boolean b) { + boolean notnull = x != null; + + boolean g1 = notnull; + g1 &= b; + if (g1) { + x.hashCode(); // OK + } + + boolean g2 = b; + g2 &= notnull; + if (g2) { + x.hashCode(); // OK + } + + boolean g3 = !notnull; + g3 |= b; + if (!g3) { + x.hashCode(); // OK + } + + boolean g4 = b; + g4 |= !notnull; + if (!g4) { + x.hashCode(); // OK + } + + boolean g5 = g1 = b & notnull; + if (g5) { + x.hashCode(); // OK + } + + g5 |= b; + if (g5) { + x.hashCode(); // NPE + } + } } diff --git a/java/ql/test/query-tests/Nullness/NullMaybe.expected b/java/ql/test/query-tests/Nullness/NullMaybe.expected index 8f72be0619f..5dfcc72f1d4 100644 --- a/java/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/java/ql/test/query-tests/Nullness/NullMaybe.expected @@ -17,6 +17,7 @@ | B.java:190:7:190:7 | o | Variable $@ may be null here because of $@ assignment. | B.java:178:5:178:20 | Object o | o | B.java:186:5:186:12 | ...=... | this | | B.java:279:7:279:7 | a | Variable $@ may be null here because of $@ assignment. | B.java:276:5:276:19 | int[] a | a | B.java:276:11:276:18 | a | this | | B.java:292:7:292:7 | b | Variable $@ may be null here because of $@ assignment. | B.java:287:5:287:44 | int[] b | b | B.java:287:11:287:43 | b | this | +| B.java:408:7:408:7 | x | Variable $@ may be null here as suggested by $@ null guard. | B.java:374:23:374:30 | x | x | B.java:375:23:375:31 | ... != ... | this | | C.java:9:44:9:45 | a2 | Variable $@ may be null here as suggested by $@ null guard. | C.java:6:5:6:23 | long[][] a2 | a2 | C.java:7:34:7:54 | ... != ... | this | | C.java:9:44:9:45 | a2 | Variable $@ may be null here because of $@ assignment. | C.java:6:5:6:23 | long[][] a2 | a2 | C.java:6:14:6:22 | a2 | this | | C.java:10:17:10:18 | a3 | Variable $@ may be null here as suggested by $@ null guard. | C.java:8:5:8:21 | long[] a3 | a3 | C.java:9:38:9:58 | ... != ... | this | diff --git a/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java b/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java index c34445f7690..549ae554097 100644 --- a/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java +++ b/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.java @@ -110,7 +110,17 @@ public class JndiInjectionTest { LdapTemplate ctx = new LdapTemplate(); Name name = new CompositeName().add(nameStr); + ctx.lookup(name); // $hasJndiInjection + ctx.lookup(name, (AttributesMapper) null); // Safe + ctx.lookup(name, (ContextMapper) null); // $hasJndiInjection + ctx.lookup(name, new String[] {}, (AttributesMapper) null); // Safe + ctx.lookup(name, new String[] {}, (ContextMapper) null); // $hasJndiInjection ctx.lookup(nameStr); // $hasJndiInjection + ctx.lookup(nameStr, (AttributesMapper) null); // Safe + ctx.lookup(nameStr, (ContextMapper) null); // $hasJndiInjection + ctx.lookup(nameStr, new String[] {}, (AttributesMapper) null); // Safe + ctx.lookup(nameStr, new String[] {}, (ContextMapper) null); // $hasJndiInjection + ctx.lookupContext(name); // $hasJndiInjection ctx.lookupContext(nameStr); // $hasJndiInjection ctx.findByDn(name, null); // $hasJndiInjection ctx.rename(name, null); // $hasJndiInjection diff --git a/java/ql/test/query-tests/security/CWE-074/options b/java/ql/test/query-tests/security/CWE-074/options index a015486520e..058d3f3e803 100644 --- a/java/ql/test/query-tests/security/CWE-074/options +++ b/java/ql/test/query-tests/security/CWE-074/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2:${testdir}/../../../stubs/Saxon-HE-9.9.1-7 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/shiro-core-1.5.2:${testdir}/../../../stubs/spring-ldap-2.3.2:${testdir}/../../../stubs/Saxon-HE-9.9.1-7:${testdir}/../../../stubs/apache-commons-logging-1.2 diff --git a/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml new file mode 100755 index 00000000000..cff71a75235 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql new file mode 100644 index 00000000000..72b95d874d2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql @@ -0,0 +1,11 @@ +import java +import TestUtilities.InlineFlowTest +import semmle.code.java.security.IntentUriPermissionManipulationQuery + +class IntentUriPermissionManipulationTest extends InlineFlowTest { + override DataFlow::Configuration getValueFlowConfig() { none() } + + override TaintTracking::Configuration getTaintFlowConfig() { + result instanceof IntentUriPermissionManipulationConf + } +} diff --git a/java/ql/test/query-tests/security/CWE-266/MainActivity.java b/java/ql/test/query-tests/security/CWE-266/MainActivity.java new file mode 100644 index 00000000000..4af80cc2b18 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/MainActivity.java @@ -0,0 +1,85 @@ +package com.example.app; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +public class MainActivity extends Activity { + + public void onCreate(Bundle savedInstance) { + { + Intent intent = getIntent(); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent extraIntent = (Intent) getIntent().getParcelableExtra("extraIntent"); + setResult(RESULT_OK, extraIntent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.setData(Uri.parse("content://safe/uri")); // Sanitizer + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + intent.setFlags(0); // Sanitizer + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + intent.setFlags( // Not properly sanitized + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.removeFlags( // Sanitizer + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + setResult(RESULT_OK, intent); // Safe + } + { + Intent intent = getIntent(); + // Combined, the following two calls are a sanitizer + intent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.removeFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + setResult(RESULT_OK, intent); // $ SPURIOUS: $ hasTaintFlow + } + { + Intent intent = getIntent(); + intent.removeFlags( // Not properly sanitized + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP); + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + { + Intent intent = getIntent(); + // Good check + if (intent.getData().equals(Uri.parse("content://safe/uri"))) { + setResult(RESULT_OK, intent); // Safe + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + { + Intent intent = getIntent(); + int flags = intent.getFlags(); + // Good check + if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0 + && (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + setResult(RESULT_OK, intent); // Safe + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + { + Intent intent = getIntent(); + int flags = intent.getFlags(); + // Insufficient check + if ((flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + setResult(RESULT_OK, intent); // $ MISSING: $ hasTaintFlow + } else { + setResult(RESULT_OK, intent); // $ hasTaintFlow + } + } + } +} diff --git a/java/ql/test/query-tests/security/CWE-266/options b/java/ql/test/query-tests/security/CWE-266/options new file mode 100644 index 00000000000..dacd3cb21df --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-266/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.expected b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java new file mode 100644 index 00000000000..5375c7c329e --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.java @@ -0,0 +1,186 @@ +import java.net.Socket; +import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.SslContextFactory; + +public class UnsafeCertTrustTest { + + /** + * Test the endpoint identification of SSL engine is set to null + */ + public void testSSLEngineEndpointIdSetNull() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(null); + sslEngine.setSSLParameters(sslParameters); + sslEngine.beginHandshake(); // $hasUnsafeCertTrust + sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust + sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust + } + + public void testSSLEngineEndpointIdSetEmpty() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(""); + sslEngine.setSSLParameters(sslParameters); + sslEngine.beginHandshake(); // $hasUnsafeCertTrust + sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust + sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust + } + + public void testSSLEngineEndpointIdSafe() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + SSLParameters sslParameters = sslEngine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslEngine.setSSLParameters(sslParameters); + sslEngine.beginHandshake(); // Safe + sslEngine.wrap(new ByteBuffer[] {}, null); // Safe + sslEngine.unwrap(null, null, 0, 0); // Safe + } + + public void testSSLEngineInServerMode() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLEngine sslEngine = sslContext.createSSLEngine(); + sslEngine.setUseClientMode(false); + sslEngine.beginHandshake(); // Safe + sslEngine.wrap(new ByteBuffer[] {}, null); // Safe + sslEngine.unwrap(null, null, 0, 0); // Safe + } + + public void testSSLSocketEndpointIdNotSet() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + socket.getOutputStream(); // $hasUnsafeCertTrust + } + + public void testSSLSocketEndpointIdSetNull() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(null); + socket.setSSLParameters(sslParameters); + socket.getOutputStream(); // $hasUnsafeCertTrust + } + + public void testSSLSocketEndpointIdSetEmpty() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm(""); + socket.setSSLParameters(sslParameters); + socket.getOutputStream(); // $hasUnsafeCertTrust + } + + public void testSSLSocketEndpointIdAfterConnecting() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + socket.getOutputStream(); // $hasUnsafeCertTrust + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + socket.setSSLParameters(sslParameters); + } + + public void testSSLSocketEndpointIdSafe() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + socket.setSSLParameters(sslParameters); + socket.getOutputStream(); // Safe + } + + public void testSSLSocketEndpointIdSafeWithModificationByReference() throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + SSLParameters sslParameters = socket.getSSLParameters(); + onSetSSLParameters(sslParameters); + socket.setSSLParameters(sslParameters); + socket.getOutputStream(); // Safe + } + + private void onSetSSLParameters(SSLParameters sslParameters) { + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + } + + public void testSSLSocketEndpointIdSafeWithConditionalSanitizer(boolean safe) throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + SSLSocket socket = (SSLSocket) socketFactory.createSocket(); + if (safe) { + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + socket.setSSLParameters(sslParameters); + } + socket.getOutputStream(); // Safe + } + + public void testSSLSocketEndpointIdSafeWithSanitizerInCast(boolean safe) throws Exception { + SSLContext sslContext = SSLContext.getInstance("TLS"); + SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + Socket socket = socketFactory.createSocket(); + SSLSocket sslSocket = (SSLSocket) socket; + SSLParameters sslParameters = sslSocket.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + sslSocket.setSSLParameters(sslParameters); + socket.getOutputStream(); // $ SPURIOUS: hasUnsafeCertTrust + } + + public void testSocketEndpointIdNotSet() throws Exception { + SocketFactory socketFactory = SocketFactory.getDefault(); + Socket socket = socketFactory.createSocket("www.example.com", 80); + socket.getOutputStream(); // Safe + } + + public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception { + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(SSLContext.getDefault()); // $hasUnsafeCertTrust + } + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setSslContextFactory(new TestSslContextFactory()); // $hasUnsafeCertTrust + } + } + + public void testRabbitMQFactorySafe() throws Exception { + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.useSslProtocol(SSLContext.getDefault()); // Safe + connectionFactory.enableHostnameVerification(); + } + { + ConnectionFactory connectionFactory = new ConnectionFactory(); + connectionFactory.setSslContextFactory(new TestSslContextFactory()); // Safe + connectionFactory.enableHostnameVerification(); + } + } + + static class TestSslContextFactory implements SslContextFactory { + + @Override + public SSLContext create(String name) { + try { + return SSLContext.getDefault(); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + + } +} diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql new file mode 100644 index 00000000000..344faa7f86b --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -0,0 +1,24 @@ +import java +import semmle.code.java.security.UnsafeCertTrustQuery +import TestUtilities.InlineExpectationsTest + +class UnsafeCertTrustTest extends InlineExpectationsTest { + UnsafeCertTrustTest() { this = "HasUnsafeCertTrustTest" } + + override string getARelevantTag() { result = "hasUnsafeCertTrust" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasUnsafeCertTrust" and + exists(Expr unsafeTrust | + unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet + or + exists(SslEndpointIdentificationFlowConfig config | + config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) + ) + | + unsafeTrust.getLocation() = location and + element = unsafeTrust.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/query-tests/security/CWE-273/options b/java/ql/test/query-tests/security/CWE-273/options new file mode 100644 index 00000000000..a97d4b5eeee --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-273/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/amqp-client-5.12.0 \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.expected b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java similarity index 54% rename from java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java rename to java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java index 5b314d464d4..17e8fc60afc 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.java @@ -39,14 +39,12 @@ public class InsecureTrustManagerTest { } @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - // BAD: Does not verify the certificate chain, allowing any certificate. - } + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - - } + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException {} } public static void main(String[] args) throws Exception { @@ -88,8 +86,9 @@ public class InsecureTrustManagerTest { } - private static void directSecureTrustManagerCall() throws NoSuchAlgorithmException, KeyStoreException, IOException, - CertificateException, FileNotFoundException, KeyManagementException, MalformedURLException { + private static void directSecureTrustManagerCall() + throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, + FileNotFoundException, KeyManagementException, MalformedURLException { SSLContext context = SSLContext.getInstance("TLS"); File certificateFile = new File("path/to/self-signed-certificate"); // Create a `KeyStore` with default type @@ -98,49 +97,46 @@ public class InsecureTrustManagerTest { keyStore.load(null, null); X509Certificate generatedCertificate; try (InputStream cert = new FileInputStream(certificateFile)) { - generatedCertificate = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(cert); + generatedCertificate = (X509Certificate) CertificateFactory.getInstance("X509") + .generateCertificate(cert); } // Add the self-signed certificate to the key store keyStore.setCertificateEntry(certificateFile.getName(), generatedCertificate); // Get default `TrustManagerFactory` - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // Use it with our modified key store that trusts our self-signed certificate tmf.init(keyStore); TrustManager[] trustManagers = tmf.getTrustManagers(); - context.init(null, trustManagers, null); // GOOD, we are not using a custom `TrustManager` but instead have - // added the self-signed certificate we want to trust to the key - // store. Note, the `trustManagers` will **only** trust this one - // certificate. + // we are not using a custom `TrustManager` but instead have added the self-signed + // certificate we want to trust to the key store. Note, the `trustManagers` will **only** + // trust this one certificate. + context.init(null, trustManagers, null); // Safe URL url = new URL("https://self-signed.badssl.com/"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(context.getSocketFactory()); } - private static void directInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { + private static void directInsecureTrustManagerCall() + throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } private static void namedVariableFlagDirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (TRUST_ALL) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void namedVariableFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (TRUST_ALL) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -148,20 +144,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (SOME_NAME_THAT_IS_NOT_A_FLAG_NAME) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } } private static void noNamedVariableFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (SOME_NAME_THAT_IS_NOT_A_FLAG_NAME) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -169,20 +160,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("TRUST_ALL"))) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void stringLiteralFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("TRUST_ALL"))) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -190,20 +176,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("SOME_NAME_THAT_IS_NOT_A_FLAG_NAME"))) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } } private static void noStringLiteralFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (Boolean.parseBoolean(System.getProperty("SOME_NAME_THAT_IS_NOT_A_FLAG_NAME"))) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -211,20 +192,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (isDisableTrust()) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // GOOD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // Safe: guarded by feature flag } } private static void methodAccessFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (isDisableTrust()) { - disableTrustManager(); // GOOD [But the disableTrustManager method itself is still detected]: Calls a - // method that install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. BUT it is guarded - // by a feature flag. + disableTrustManager(); // Safe: guarded by feature flag } } @@ -232,20 +208,15 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { if (is42TheAnswerForEverything()) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } } private static void noMethodAccessFlagIndirectInsecureTrustManagerCall() throws NoSuchAlgorithmException, KeyManagementException { if (is42TheAnswerForEverything()) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -254,10 +225,8 @@ public class InsecureTrustManagerTest { String schemaFromHttpRequest = "HTTPS"; if (schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -265,10 +234,7 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { String schemaFromHttpRequest = "HTTPS"; if (schemaFromHttpRequest.equalsIgnoreCase("https")) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -277,10 +243,8 @@ public class InsecureTrustManagerTest { String schemaFromHttpRequest = "HTTPS"; if (!schemaFromHttpRequest.equalsIgnoreCase("https")) { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } } @@ -288,10 +252,7 @@ public class InsecureTrustManagerTest { throws NoSuchAlgorithmException, KeyManagementException { String schemaFromHttpRequest = "HTTPS"; if (!schemaFromHttpRequest.equalsIgnoreCase("https")) { - disableTrustManager(); // BAD [This is detected in the disableTrustManager method]: Calls a method that - // install a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag. + disableTrustManager(); // Alert is in the method } } @@ -302,10 +263,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -316,10 +275,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -330,10 +287,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -344,10 +299,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -358,10 +311,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -372,11 +323,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. - + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } private static void isEqualsIgnoreCaseNOTGuardingDirectInsecureTrustManagerCall() @@ -387,10 +335,8 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } @@ -402,19 +348,15 @@ public class InsecureTrustManagerTest { } SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the certificate - // chain, allowing any certificate. It is NOT guarded - // by a feature flag, because it is outside the if and it is NOT a valid flag. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } - private static void disableTrustManager() throws NoSuchAlgorithmException, KeyManagementException { + private static void disableTrustManager() + throws NoSuchAlgorithmException, KeyManagementException { SSLContext context = SSLContext.getInstance("TLS"); - TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() }; - context.init(null, trustManager, null); // BAD: Uses a `TrustManager` that does not verify the - // certificate - // chain, allowing any certificate. The method name suggests that this may be - // intentional, but we flag it anyway. + TrustManager[] trustManager = new TrustManager[] {new InsecureTrustManager()}; + context.init(null, trustManager, null); // $ hasValueFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql new file mode 100644 index 00000000000..b2922d13d69 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql @@ -0,0 +1,9 @@ +import java +import semmle.code.java.security.InsecureTrustManagerQuery +import TestUtilities.InlineFlowTest + +class InsecureTrustManagerTest extends InlineFlowTest { + override DataFlow::Configuration getValueFlowConfig() { + result = any(InsecureTrustManagerConfiguration c) + } +} diff --git a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java new file mode 100644 index 00000000000..44dd5df1a26 --- /dev/null +++ b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/ConnectionFactory.java @@ -0,0 +1,232 @@ +// Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.Predicate; +import static java.util.concurrent.TimeUnit.MINUTES; + +public class ConnectionFactory implements Cloneable { + public static final int DEFAULT_CHANNEL_RPC_TIMEOUT = (int) MINUTES.toMillis(10); + + public String getHost() { + return null; + } + + public void setHost(String host) {} + + public static int portOrDefault(int port, boolean ssl) { + return 0; + } + + public int getPort() { + return 0; + } + + public void setPort(int port) {} + + public String getUsername() { + return null; + } + + public void setUsername(String username) {} + + public String getPassword() { + return null; + } + + public void setPassword(String password) {} + + public String getVirtualHost() { + return null; + } + + public void setVirtualHost(String virtualHost) {} + + public void setUri(URI uri) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {} + + public void setUri(String uriString) + throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException {} + + public int getRequestedChannelMax() { + return 0; + } + + public void setRequestedChannelMax(int requestedChannelMax) {} + + public int getRequestedFrameMax() { + return 0; + } + + public void setRequestedFrameMax(int requestedFrameMax) {} + + public int getRequestedHeartbeat() { + return 0; + } + + public void setConnectionTimeout(int timeout) {} + + public int getConnectionTimeout() { + return 0; + } + + public int getHandshakeTimeout() { + return 0; + } + + public void setHandshakeTimeout(int timeout) {} + + public void setShutdownTimeout(int shutdownTimeout) {} + + public int getShutdownTimeout() { + return 0; + } + + public void setRequestedHeartbeat(int requestedHeartbeat) {} + + public Map getClientProperties() { + return null; + } + + public void setClientProperties(Map clientProperties) {} + + public SocketFactory getSocketFactory() { + return null; + } + + public void setSocketFactory(SocketFactory factory) {} + + public void setSharedExecutor(ExecutorService executor) {} + + public void setShutdownExecutor(ExecutorService executor) {} + + public void setHeartbeatExecutor(ScheduledExecutorService executor) {} + + public ThreadFactory getThreadFactory() { + return null; + } + + public void setThreadFactory(ThreadFactory threadFactory) {} + + public boolean isSSL() { + return false; + } + + public void useSslProtocol() throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(String protocol) + throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(String protocol, TrustManager trustManager) + throws NoSuchAlgorithmException, KeyManagementException {} + + public void useSslProtocol(SSLContext context) {} + + public void enableHostnameVerification() {} + + public static String computeDefaultTlsProtocol(String[] supportedProtocols) { + return null; + } + + public boolean isAutomaticRecoveryEnabled() { + return false; + } + + public void setAutomaticRecoveryEnabled(boolean automaticRecovery) {} + + public boolean isTopologyRecoveryEnabled() { + return false; + } + + public void setTopologyRecoveryEnabled(boolean topologyRecovery) {} + + public ExecutorService getTopologyRecoveryExecutor() { + return null; + } + + public void setTopologyRecoveryExecutor(final ExecutorService topologyRecoveryExecutor) {} + + public ConnectionFactory load(String propertyFileLocation) throws IOException { + return null; + } + + public ConnectionFactory load(String propertyFileLocation, String prefix) throws IOException { + return null; + } + + public ConnectionFactory load(Properties properties) { + return null; + } + + public ConnectionFactory load(Properties properties, String prefix) { + return null; + } + + public ConnectionFactory load(Map properties) { + return null; + } + + public ConnectionFactory load(Map properties, String prefix) { + return null; + } + + public long getNetworkRecoveryInterval() { + return 0; + } + + public void setNetworkRecoveryInterval(int networkRecoveryInterval) {} + + public void setNetworkRecoveryInterval(long networkRecoveryInterval) {} + + public void useNio() {} + + public void useBlockingIo() {} + + public void setChannelRpcTimeout(int channelRpcTimeout) {} + + public int getChannelRpcTimeout() { + return 0; + } + + public void setSslContextFactory(SslContextFactory sslContextFactory) {} + + public void setChannelShouldCheckRpcResponseType(boolean channelShouldCheckRpcResponseType) {} + + public boolean isChannelShouldCheckRpcResponseType() { + return false; + } + + public void setWorkPoolTimeout(int workPoolTimeout) {} + + public int getWorkPoolTimeout() { + return 0; + } + + public static int ensureUnsignedShort(int value) { + return 0; + } + +} diff --git a/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java new file mode 100644 index 00000000000..ae17f15437d --- /dev/null +++ b/java/ql/test/stubs/amqp-client-5.12.0/com/rabbitmq/client/SslContextFactory.java @@ -0,0 +1,23 @@ +// Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. +// +// This software, the RabbitMQ Java client library, is triple-licensed under the +// Mozilla Public License 2.0 ("MPL"), the GNU General Public License version 2 +// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see +// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL, +// please see LICENSE-APACHE2. +// +// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, +// either express or implied. See the LICENSE file for specific language governing +// rights and limitations of this software. +// +// If you have any questions regarding licensing, please contact us at +// info@rabbitmq.com. + +package com.rabbitmq.client; + +import javax.net.ssl.SSLContext; + +public interface SslContextFactory { + SSLContext create(String name); + +} diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java index e06f81dcef1..5e5f71dcd25 100644 --- a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java +++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java @@ -15,31 +15,31 @@ package android.app; import android.annotation.Nullable; +import android.content.ComponentCallbacks2; import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; - -public class Fragment { - +public class Fragment implements ComponentCallbacks2 { public static class SavedState implements Parcelable { - - @Override - public void writeToParcel(Parcel dest, int flags) {} - @Override public int describeContents() { return 0; } + + @Override + public void writeToParcel(Parcel dest, int flags) {} + } static public class InstantiationException { public InstantiationException(String msg, Exception cause) {} - } + public Fragment() {} public static Fragment instantiate(Context context, String fname) { @@ -65,4 +65,18 @@ public class Fragment { return null; } + @Override + public void onConfigurationChanged(Configuration p0) {} + + @Override + public void onLowMemory() {} + + @Override + public void onTrimMemory(int p0) {} + + public void startActivityForResult(Intent intent, int requestCode) {} + + public void startActivityForResult(Intent intent, int requestCode, Bundle options) {} + + public void onActivityResult(int requestCode, int resultCode, Intent data) {} } diff --git a/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiCallback.java b/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiCallback.java new file mode 100644 index 00000000000..6b71341baf8 --- /dev/null +++ b/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.shiro.jndi.JndiCallback for testing purposes + +package org.apache.shiro.jndi; + +import javax.naming.Context; + +public interface JndiCallback +{ + Object doInContext(Context p0); +} diff --git a/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiTemplate.java b/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiTemplate.java index 936be2abf7c..4fe4fc306d0 100644 --- a/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiTemplate.java +++ b/java/ql/test/stubs/shiro-core-1.5.2/org/apache/shiro/jndi/JndiTemplate.java @@ -1,13 +1,22 @@ +// Generated automatically from org.apache.shiro.jndi.JndiTemplate for testing purposes + package org.apache.shiro.jndi; -import javax.naming.NamingException; +import java.util.Properties; +import javax.naming.Context; +import org.apache.shiro.jndi.JndiCallback; -public class JndiTemplate { - public Object lookup(final String name) throws NamingException { - return new Object(); - } - - public Object lookup(String name, Class requiredType) throws NamingException { - return new Object(); - } -} \ No newline at end of file +public class JndiTemplate +{ + protected Context createInitialContext(){ return null; } + public JndiTemplate(){} + public JndiTemplate(Properties p0){} + public Object execute(JndiCallback p0){ return null; } + public Object lookup(String p0){ return null; } + public Object lookup(String p0, Class p1){ return null; } + public Properties getEnvironment(){ return null; } + public void bind(String p0, Object p1){} + public void rebind(String p0, Object p1){} + public void setEnvironment(Properties p0){} + public void unbind(String p0){} +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/LdapDataEntry.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/LdapDataEntry.java new file mode 100644 index 00000000000..4dbd3da1ca5 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/LdapDataEntry.java @@ -0,0 +1,25 @@ +// Generated automatically from org.springframework.LdapDataEntry for testing purposes + +package org.springframework; + +import java.util.SortedSet; +import javax.naming.Name; +import javax.naming.directory.Attributes; + +public interface LdapDataEntry +{ + Attributes getAttributes(); + Name getDn(); + Object getObjectAttribute(String p0); + Object[] getObjectAttributes(String p0); + SortedSet getAttributeSortedStringSet(String p0); + String getStringAttribute(String p0); + String[] getStringAttributes(String p0); + boolean attributeExists(String p0); + void addAttributeValue(String p0, Object p1); + void addAttributeValue(String p0, Object p1, boolean p2); + void removeAttributeValue(String p0, Object p1); + void setAttributeValue(String p0, Object p1); + void setAttributeValues(String p0, Object[] p1); + void setAttributeValues(String p0, Object[] p1, boolean p2); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributeModificationsAware.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributeModificationsAware.java new file mode 100644 index 00000000000..29c6a68b4be --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributeModificationsAware.java @@ -0,0 +1,10 @@ +// Generated automatically from org.springframework.ldap.core.AttributeModificationsAware for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.directory.ModificationItem; + +public interface AttributeModificationsAware +{ + ModificationItem[] getModificationItems(); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributesMapper.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributesMapper.java index af734cea237..4d595bc1138 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributesMapper.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AttributesMapper.java @@ -1,3 +1,10 @@ +// Generated automatically from org.springframework.ldap.core.AttributesMapper for testing purposes + package org.springframework.ldap.core; -public interface AttributesMapper {} \ No newline at end of file +import javax.naming.directory.Attributes; + +public interface AttributesMapper +{ + T mapFromAttributes(Attributes p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java new file mode 100644 index 00000000000..146a44f79ab --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextCallback.java @@ -0,0 +1,11 @@ +// Generated automatically from org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; +import org.springframework.ldap.core.LdapEntryIdentification; + +public interface AuthenticatedLdapEntryContextCallback +{ + void executeWithContext(DirContext p0, LdapEntryIdentification p1); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextMapper.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextMapper.java new file mode 100644 index 00000000000..f6a9a2fcdd8 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticatedLdapEntryContextMapper.java @@ -0,0 +1,11 @@ +// Generated automatically from org.springframework.ldap.core.AuthenticatedLdapEntryContextMapper for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; +import org.springframework.ldap.core.LdapEntryIdentification; + +public interface AuthenticatedLdapEntryContextMapper +{ + T mapWithContext(DirContext p0, LdapEntryIdentification p1); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticationErrorCallback.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticationErrorCallback.java new file mode 100644 index 00000000000..1865df5337b --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/AuthenticationErrorCallback.java @@ -0,0 +1,9 @@ +// Generated automatically from org.springframework.ldap.core.AuthenticationErrorCallback for testing purposes + +package org.springframework.ldap.core; + + +public interface AuthenticationErrorCallback +{ + void execute(Exception p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextExecutor.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextExecutor.java new file mode 100644 index 00000000000..36174a2ea0e --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextExecutor.java @@ -0,0 +1,10 @@ +// Generated automatically from org.springframework.ldap.core.ContextExecutor for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; + +public interface ContextExecutor +{ + T executeWithContext(DirContext p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextMapper.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextMapper.java index 951015b637e..8298b482ce3 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextMapper.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextMapper.java @@ -1,4 +1,9 @@ +// Generated automatically from org.springframework.ldap.core.ContextMapper for testing purposes + package org.springframework.ldap.core; -public interface ContextMapper { + +public interface ContextMapper +{ + T mapFromContext(Object p0); } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextSource.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextSource.java new file mode 100644 index 00000000000..620791766ba --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/ContextSource.java @@ -0,0 +1,12 @@ +// Generated automatically from org.springframework.ldap.core.ContextSource for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.directory.DirContext; + +public interface ContextSource +{ + DirContext getContext(String p0, String p1); + DirContext getReadOnlyContext(); + DirContext getReadWriteContext(); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextOperations.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextOperations.java index 682de892a42..332aabc298c 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextOperations.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextOperations.java @@ -1,4 +1,19 @@ +// Generated automatically from org.springframework.ldap.core.DirContextOperations for testing purposes + package org.springframework.ldap.core; -public interface DirContextOperations { +import javax.naming.Name; +import javax.naming.directory.DirContext; +import org.springframework.LdapDataEntry; +import org.springframework.ldap.core.AttributeModificationsAware; + +public interface DirContextOperations extends AttributeModificationsAware, DirContext, LdapDataEntry +{ + String getNameInNamespace(); + String getReferralUrl(); + String[] getNamesOfModifiedAttributes(); + boolean isReferral(); + boolean isUpdateMode(); + void setDn(Name p0); + void update(); } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextProcessor.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextProcessor.java index 06c2b9aa544..6cfcdfcd41c 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextProcessor.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DirContextProcessor.java @@ -1,3 +1,11 @@ +// Generated automatically from org.springframework.ldap.core.DirContextProcessor for testing purposes + package org.springframework.ldap.core; -public interface DirContextProcessor {} \ No newline at end of file +import javax.naming.directory.DirContext; + +public interface DirContextProcessor +{ + void postProcess(DirContext p0); + void preProcess(DirContext p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DistinguishedName.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DistinguishedName.java new file mode 100644 index 00000000000..fcb930eefac --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/DistinguishedName.java @@ -0,0 +1,60 @@ +// Generated automatically from org.springframework.ldap.core.DistinguishedName for testing purposes + +package org.springframework.ldap.core; + +import java.util.Enumeration; +import java.util.List; +import javax.naming.Name; +import org.springframework.ldap.core.LdapRdn; + +public class DistinguishedName implements Name +{ + protected final void parse(String p0){} + public DistinguishedName append(DistinguishedName p0){ return null; } + public DistinguishedName append(String p0, String p1){ return null; } + public DistinguishedName immutableDistinguishedName(){ return null; } + public DistinguishedName(){} + public DistinguishedName(List p0){} + public DistinguishedName(Name p0){} + public DistinguishedName(String p0){} + public Enumeration getAll(){ return null; } + public LdapRdn getLdapRdn(String p0){ return null; } + public LdapRdn getLdapRdn(int p0){ return null; } + public LdapRdn removeFirst(){ return null; } + public LdapRdn removeLast(){ return null; } + public List getNames(){ return null; } + public Name add(String p0){ return null; } + public Name add(int p0, String p1){ return null; } + public Name addAll(Name p0){ return null; } + public Name addAll(int p0, Name p1){ return null; } + public Name getPrefix(int p0){ return null; } + public Name getSuffix(int p0){ return null; } + public Object clone(){ return null; } + public Object remove(int p0){ return null; } + public String encode(){ return null; } + public String get(int p0){ return null; } + public String getValue(String p0){ return null; } + public String toCompactString(){ return null; } + public String toString(){ return null; } + public String toUrl(){ return null; } + public boolean contains(DistinguishedName p0){ return false; } + public boolean endsWith(Name p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean startsWith(Name p0){ return false; } + public int compareTo(Object p0){ return 0; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public static DistinguishedName EMPTY_PATH = null; + public static DistinguishedName immutableDistinguishedName(String p0){ return null; } + public static String KEY_CASE_FOLD_LOWER = null; + public static String KEY_CASE_FOLD_NONE = null; + public static String KEY_CASE_FOLD_PROPERTY = null; + public static String KEY_CASE_FOLD_UPPER = null; + public static String SPACED_DN_FORMAT_PROPERTY = null; + public void add(LdapRdn p0){} + public void add(String p0, String p1){} + public void add(int p0, LdapRdn p1){} + public void prepend(DistinguishedName p0){} + public void removeFirst(Name p0){} +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapEntryIdentification.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapEntryIdentification.java new file mode 100644 index 00000000000..d01556f4bd7 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapEntryIdentification.java @@ -0,0 +1,19 @@ +// Generated automatically from org.springframework.ldap.core.LdapEntryIdentification for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.ldap.LdapName; +import org.springframework.ldap.core.DistinguishedName; + +public class LdapEntryIdentification +{ + protected LdapEntryIdentification() {} + public DistinguishedName getAbsoluteDn(){ return null; } + public DistinguishedName getRelativeDn(){ return null; } + public LdapEntryIdentification(DistinguishedName p0, DistinguishedName p1){} + public LdapEntryIdentification(LdapName p0, LdapName p1){} + public LdapName getAbsoluteName(){ return null; } + public LdapName getRelativeName(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapOperations.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapOperations.java index 91cac00e673..b1bcc193112 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapOperations.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapOperations.java @@ -1,84 +1,129 @@ +// Generated automatically from org.springframework.ldap.core.LdapOperations for testing purposes + package org.springframework.ldap.core; -import java.util.*; - +import java.util.List; import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; - +import org.springframework.ldap.core.AttributesMapper; +import org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback; +import org.springframework.ldap.core.AuthenticatedLdapEntryContextMapper; +import org.springframework.ldap.core.AuthenticationErrorCallback; +import org.springframework.ldap.core.ContextExecutor; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DirContextProcessor; +import org.springframework.ldap.core.NameClassPairCallbackHandler; +import org.springframework.ldap.core.NameClassPairMapper; +import org.springframework.ldap.core.SearchExecutor; import org.springframework.ldap.filter.Filter; - +import org.springframework.ldap.odm.core.ObjectDirectoryMapper; import org.springframework.ldap.query.LdapQuery; -public interface LdapOperations { - void authenticate(LdapQuery query, String password); - - boolean authenticate(Name base, String filter, String password); - - List find(Name base, Filter filter, SearchControls searchControls, final Class clazz); - - List find(LdapQuery query, Class clazz); - - T findOne(LdapQuery query, Class clazz); - - void search(String base, String filter, int searchScope, boolean returningObjFlag, - NameClassPairCallbackHandler handler); - - void search(final String base, final String filter, final SearchControls controls, - NameClassPairCallbackHandler handler); - - void search(final String base, final String filter, final SearchControls controls, - NameClassPairCallbackHandler handler, DirContextProcessor processor); - - void search(String base, String filter, NameClassPairCallbackHandler handler); - - List search(String base, String filter, int searchScope, String[] attrs, - AttributesMapper mapper); - - List search(String base, String filter, int searchScope, AttributesMapper mapper); - - List search(String base, String filter, AttributesMapper mapper); - - List search(String base, String filter, int searchScope, String[] attrs, - ContextMapper mapper); - - List search(String base, String filter, int searchScope, ContextMapper mapper); - - List search(String base, String filter, ContextMapper mapper); - - List search(String base, String filter, SearchControls controls, - ContextMapper mapper); - - List search(String base, String filter, SearchControls controls, - AttributesMapper mapper); - - List search(String base, String filter, SearchControls controls, - AttributesMapper mapper, DirContextProcessor processor); - - List search(String base, String filter, SearchControls controls, ContextMapper mapper, - DirContextProcessor processor); - - DirContextOperations searchForContext(LdapQuery query); - - T searchForObject(Name base, String filter, ContextMapper mapper); - - T searchForObject(String base, String filter, ContextMapper mapper); - - T searchForObject(String base, String filter, SearchControls searchControls, - ContextMapper mapper); - - Object lookup(final String dn); - - DirContextOperations lookupContext(String dn); - - T findByDn(Name dn, final Class clazz); - - void rename(final Name oldDn, final Name newDn); - - List list(final Name base); - - List listBindings(final Name base); - - void unbind(final String dn); - - void unbind(final String dn, boolean recursive); +public interface LdapOperations +{ + List find(LdapQuery p0, Class p1); + List find(Name p0, Filter p1, SearchControls p2, Class p3); + List findAll(Class p0); + List findAll(Name p0, SearchControls p1, Class p2); + List list(Name p0, NameClassPairMapper p1); + List list(String p0, NameClassPairMapper p1); + List listBindings(Name p0, ContextMapper p1); + List listBindings(Name p0, NameClassPairMapper p1); + List listBindings(String p0, ContextMapper p1); + List listBindings(String p0, NameClassPairMapper p1); + List search(LdapQuery p0, AttributesMapper p1); + List search(LdapQuery p0, ContextMapper p1); + List search(Name p0, String p1, AttributesMapper p2); + List search(Name p0, String p1, ContextMapper p2); + List search(Name p0, String p1, SearchControls p2, AttributesMapper p3); + List search(Name p0, String p1, SearchControls p2, AttributesMapper p3, DirContextProcessor p4); + List search(Name p0, String p1, SearchControls p2, ContextMapper p3); + List search(Name p0, String p1, SearchControls p2, ContextMapper p3, DirContextProcessor p4); + List search(Name p0, String p1, int p2, AttributesMapper p3); + List search(Name p0, String p1, int p2, ContextMapper p3); + List search(Name p0, String p1, int p2, String[] p3, AttributesMapper p4); + List search(Name p0, String p1, int p2, String[] p3, ContextMapper p4); + List search(String p0, String p1, AttributesMapper p2); + List search(String p0, String p1, ContextMapper p2); + List search(String p0, String p1, SearchControls p2, AttributesMapper p3); + List search(String p0, String p1, SearchControls p2, AttributesMapper p3, DirContextProcessor p4); + List search(String p0, String p1, SearchControls p2, ContextMapper p3); + List search(String p0, String p1, SearchControls p2, ContextMapper p3, DirContextProcessor p4); + List search(String p0, String p1, int p2, AttributesMapper p3); + List search(String p0, String p1, int p2, ContextMapper p3); + List search(String p0, String p1, int p2, String[] p3, AttributesMapper p4); + List search(String p0, String p1, int p2, String[] p3, ContextMapper p4); + T authenticate(LdapQuery p0, String p1, AuthenticatedLdapEntryContextMapper p2); + T executeReadOnly(ContextExecutor p0); + T executeReadWrite(ContextExecutor p0); + T findByDn(Name p0, Class p1); + T findOne(LdapQuery p0, Class p1); + T lookup(Name p0, AttributesMapper p1); + T lookup(Name p0, ContextMapper p1); + T lookup(Name p0, String[] p1, AttributesMapper p2); + T lookup(Name p0, String[] p1, ContextMapper p2); + T lookup(String p0, AttributesMapper p1); + T lookup(String p0, ContextMapper p1); + T lookup(String p0, String[] p1, AttributesMapper p2); + T lookup(String p0, String[] p1, ContextMapper p2); + T searchForObject(LdapQuery p0, ContextMapper p1); + T searchForObject(Name p0, String p1, ContextMapper p2); + T searchForObject(Name p0, String p1, SearchControls p2, ContextMapper p3); + T searchForObject(String p0, String p1, ContextMapper p2); + T searchForObject(String p0, String p1, SearchControls p2, ContextMapper p3); + DirContextOperations lookupContext(Name p0); + DirContextOperations lookupContext(String p0); + DirContextOperations searchForContext(LdapQuery p0); + List list(Name p0); + List list(String p0); + List listBindings(Name p0); + List listBindings(String p0); + Object lookup(Name p0); + Object lookup(String p0); + ObjectDirectoryMapper getObjectDirectoryMapper(); + boolean authenticate(Name p0, String p1, String p2); + boolean authenticate(Name p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3); + boolean authenticate(Name p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3, AuthenticationErrorCallback p4); + boolean authenticate(Name p0, String p1, String p2, AuthenticationErrorCallback p3); + boolean authenticate(String p0, String p1, String p2); + boolean authenticate(String p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3); + boolean authenticate(String p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3, AuthenticationErrorCallback p4); + boolean authenticate(String p0, String p1, String p2, AuthenticationErrorCallback p3); + void authenticate(LdapQuery p0, String p1); + void bind(DirContextOperations p0); + void bind(Name p0, Object p1, Attributes p2); + void bind(String p0, Object p1, Attributes p2); + void create(Object p0); + void delete(Object p0); + void list(Name p0, NameClassPairCallbackHandler p1); + void list(String p0, NameClassPairCallbackHandler p1); + void listBindings(Name p0, NameClassPairCallbackHandler p1); + void listBindings(String p0, NameClassPairCallbackHandler p1); + void modifyAttributes(DirContextOperations p0); + void modifyAttributes(Name p0, ModificationItem[] p1); + void modifyAttributes(String p0, ModificationItem[] p1); + void rebind(DirContextOperations p0); + void rebind(Name p0, Object p1, Attributes p2); + void rebind(String p0, Object p1, Attributes p2); + void rename(Name p0, Name p1); + void rename(String p0, String p1); + void search(LdapQuery p0, NameClassPairCallbackHandler p1); + void search(Name p0, String p1, NameClassPairCallbackHandler p2); + void search(Name p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3); + void search(Name p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3, DirContextProcessor p4); + void search(Name p0, String p1, int p2, boolean p3, NameClassPairCallbackHandler p4); + void search(SearchExecutor p0, NameClassPairCallbackHandler p1); + void search(SearchExecutor p0, NameClassPairCallbackHandler p1, DirContextProcessor p2); + void search(String p0, String p1, NameClassPairCallbackHandler p2); + void search(String p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3); + void search(String p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3, DirContextProcessor p4); + void search(String p0, String p1, int p2, boolean p3, NameClassPairCallbackHandler p4); + void unbind(Name p0); + void unbind(Name p0, boolean p1); + void unbind(String p0); + void unbind(String p0, boolean p1); + void update(Object p0); } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdn.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdn.java new file mode 100644 index 00000000000..048e3e27936 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdn.java @@ -0,0 +1,28 @@ +// Generated automatically from org.springframework.ldap.core.LdapRdn for testing purposes + +package org.springframework.ldap.core; + +import java.io.Serializable; +import java.util.List; +import org.springframework.ldap.core.LdapRdnComponent; + +public class LdapRdn implements Comparable, Serializable +{ + public LdapRdn immutableLdapRdn(){ return null; } + public LdapRdn(){} + public LdapRdn(String p0){} + public LdapRdn(String p0, String p1){} + public LdapRdnComponent getComponent(){ return null; } + public LdapRdnComponent getComponent(int p0){ return null; } + public List getComponents(){ return null; } + public String encodeUrl(){ return null; } + public String getKey(){ return null; } + public String getLdapEncoded(){ return null; } + public String getValue(){ return null; } + public String getValue(String p0){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(Object p0){ return 0; } + public int hashCode(){ return 0; } + public void addComponent(LdapRdnComponent p0){} +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdnComponent.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdnComponent.java new file mode 100644 index 00000000000..00ddb520aa8 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapRdnComponent.java @@ -0,0 +1,25 @@ +// Generated automatically from org.springframework.ldap.core.LdapRdnComponent for testing purposes + +package org.springframework.ldap.core; + +import java.io.Serializable; + +public class LdapRdnComponent implements Comparable, Serializable +{ + protected LdapRdnComponent() {} + protected String encodeLdap(){ return null; } + public LdapRdnComponent immutableLdapRdnComponent(){ return null; } + public LdapRdnComponent(String p0, String p1){} + public LdapRdnComponent(String p0, String p1, boolean p2){} + public String encodeUrl(){ return null; } + public String getKey(){ return null; } + public String getLdapEncoded(){ return null; } + public String getValue(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(Object p0){ return 0; } + public int hashCode(){ return 0; } + public static boolean DONT_DECODE_VALUE = false; + public void setKey(String p0){} + public void setValue(String p0){} +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapTemplate.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapTemplate.java index fee83cf4ec8..fe98e2bfceb 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapTemplate.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/LdapTemplate.java @@ -1,76 +1,146 @@ +// Generated automatically from org.springframework.ldap.core.LdapTemplate for testing purposes + package org.springframework.ldap.core; -import org.springframework.beans.factory.InitializingBean; - -import java.util.*; - +import java.util.List; import javax.naming.Name; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; - +import org.springframework.beans.factory.InitializingBean; +import org.springframework.ldap.core.AttributesMapper; +import org.springframework.ldap.core.AuthenticatedLdapEntryContextCallback; +import org.springframework.ldap.core.AuthenticatedLdapEntryContextMapper; +import org.springframework.ldap.core.AuthenticationErrorCallback; +import org.springframework.ldap.core.ContextExecutor; +import org.springframework.ldap.core.ContextMapper; +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DirContextProcessor; +import org.springframework.ldap.core.LdapOperations; +import org.springframework.ldap.core.NameClassPairCallbackHandler; +import org.springframework.ldap.core.NameClassPairMapper; +import org.springframework.ldap.core.SearchExecutor; import org.springframework.ldap.filter.Filter; - +import org.springframework.ldap.odm.core.ObjectDirectoryMapper; import org.springframework.ldap.query.LdapQuery; -public class LdapTemplate implements LdapOperations, InitializingBean { - public void authenticate(LdapQuery query, String password) { } - - public boolean authenticate(Name base, String filter, String password) { return true; } - - public List find(Name base, Filter filter, SearchControls searchControls, final Class clazz) { return null; } - - public List find(LdapQuery query, Class clazz) { return null; } - - public T findOne(LdapQuery query, Class clazz) { return null; } - - public void search(String base, String filter, int searchScope, boolean returningObjFlag, NameClassPairCallbackHandler handler) { } - - public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler) {} - - public void search(final String base, final String filter, final SearchControls controls, NameClassPairCallbackHandler handler, DirContextProcessor processor) {} - - public void search(String base, String filter, NameClassPairCallbackHandler handler) {} - - public List search(String base, String filter, int searchScope, String[] attrs, AttributesMapper mapper) { return null; } - - public List search(String base, String filter, int searchScope, AttributesMapper mapper) { return null; } - - public List search(String base, String filter, AttributesMapper mapper) { return null; } - - public List search(String base, String filter, int searchScope, String[] attrs, ContextMapper mapper) { return null; } - - public List search(String base, String filter, int searchScope, ContextMapper mapper) { return null; } - - public List search(String base, String filter, ContextMapper mapper) { return null; } - - public List search(String base, String filter, SearchControls controls, ContextMapper mapper) { return null; } - - public List search(String base, String filter, SearchControls controls, AttributesMapper mapper) { return null; } - - public List search(String base, String filter, SearchControls controls, AttributesMapper mapper, DirContextProcessor processor) { return null; } - - public List search(String base, String filter, SearchControls controls, ContextMapper mapper, DirContextProcessor processor) { return null; } - - public DirContextOperations searchForContext(LdapQuery query) { return null; } - - public T searchForObject(Name base, String filter, ContextMapper mapper) { return null; } - - public T searchForObject(String base, String filter, ContextMapper mapper) { return null; } - - public T searchForObject(String base, String filter, SearchControls searchControls, ContextMapper mapper) { return null; } - - public Object lookup(final String dn) { return new Object(); } - - public DirContextOperations lookupContext(String dn) { return null; } - - public T findByDn(Name dn, final Class clazz) { return null; } - - public void rename(final Name oldDn, final Name newDn) {} - - public List list(final Name base) { return null; } - - public List listBindings(final Name base) { return null; } - - public void unbind(final String dn) {} - - public void unbind(final String dn, boolean recursive) {} +public class LdapTemplate implements InitializingBean, LdapOperations +{ + protected void deleteRecursively(DirContext p0, Name p1){} + public List find(LdapQuery p0, Class p1){ return null; } + public List find(Name p0, Filter p1, SearchControls p2, Class p3){ return null; } + public List findAll(Class p0){ return null; } + public List findAll(Name p0, SearchControls p1, Class p2){ return null; } + public List list(Name p0, NameClassPairMapper p1){ return null; } + public List list(String p0, NameClassPairMapper p1){ return null; } + public List listBindings(Name p0, ContextMapper p1){ return null; } + public List listBindings(Name p0, NameClassPairMapper p1){ return null; } + public List listBindings(String p0, ContextMapper p1){ return null; } + public List listBindings(String p0, NameClassPairMapper p1){ return null; } + public List search(LdapQuery p0, AttributesMapper p1){ return null; } + public List search(LdapQuery p0, ContextMapper p1){ return null; } + public List search(Name p0, String p1, AttributesMapper p2){ return null; } + public List search(Name p0, String p1, ContextMapper p2){ return null; } + public List search(Name p0, String p1, SearchControls p2, AttributesMapper p3){ return null; } + public List search(Name p0, String p1, SearchControls p2, AttributesMapper p3, DirContextProcessor p4){ return null; } + public List search(Name p0, String p1, SearchControls p2, ContextMapper p3){ return null; } + public List search(Name p0, String p1, SearchControls p2, ContextMapper p3, DirContextProcessor p4){ return null; } + public List search(Name p0, String p1, int p2, AttributesMapper p3){ return null; } + public List search(Name p0, String p1, int p2, ContextMapper p3){ return null; } + public List search(Name p0, String p1, int p2, String[] p3, AttributesMapper p4){ return null; } + public List search(Name p0, String p1, int p2, String[] p3, ContextMapper p4){ return null; } + public List search(String p0, String p1, AttributesMapper p2){ return null; } + public List search(String p0, String p1, ContextMapper p2){ return null; } + public List search(String p0, String p1, SearchControls p2, AttributesMapper p3){ return null; } + public List search(String p0, String p1, SearchControls p2, AttributesMapper p3, DirContextProcessor p4){ return null; } + public List search(String p0, String p1, SearchControls p2, ContextMapper p3){ return null; } + public List search(String p0, String p1, SearchControls p2, ContextMapper p3, DirContextProcessor p4){ return null; } + public List search(String p0, String p1, int p2, AttributesMapper p3){ return null; } + public List search(String p0, String p1, int p2, ContextMapper p3){ return null; } + public List search(String p0, String p1, int p2, String[] p3, AttributesMapper p4){ return null; } + public List search(String p0, String p1, int p2, String[] p3, ContextMapper p4){ return null; } + public T authenticate(LdapQuery p0, String p1, AuthenticatedLdapEntryContextMapper p2){ return null; } + public T executeReadOnly(ContextExecutor p0){ return null; } + public T executeReadWrite(ContextExecutor p0){ return null; } + public T findByDn(Name p0, Class p1){ return null; } + public T findOne(LdapQuery p0, Class p1){ return null; } + public T lookup(Name p0, AttributesMapper p1){ return null; } + public T lookup(Name p0, ContextMapper p1){ return null; } + public T lookup(Name p0, String[] p1, AttributesMapper p2){ return null; } + public T lookup(Name p0, String[] p1, ContextMapper p2){ return null; } + public T lookup(String p0, AttributesMapper p1){ return null; } + public T lookup(String p0, ContextMapper p1){ return null; } + public T lookup(String p0, String[] p1, AttributesMapper p2){ return null; } + public T lookup(String p0, String[] p1, ContextMapper p2){ return null; } + public T searchForObject(LdapQuery p0, ContextMapper p1){ return null; } + public T searchForObject(Name p0, String p1, ContextMapper p2){ return null; } + public T searchForObject(Name p0, String p1, SearchControls p2, ContextMapper p3){ return null; } + public T searchForObject(String p0, String p1, ContextMapper p2){ return null; } + public T searchForObject(String p0, String p1, SearchControls p2, ContextMapper p3){ return null; } + public ContextSource getContextSource(){ return null; } + public DirContextOperations lookupContext(Name p0){ return null; } + public DirContextOperations lookupContext(String p0){ return null; } + public DirContextOperations searchForContext(LdapQuery p0){ return null; } + public LdapTemplate(){} + public LdapTemplate(ContextSource p0){} + public List list(Name p0){ return null; } + public List list(String p0){ return null; } + public List listBindings(Name p0){ return null; } + public List listBindings(String p0){ return null; } + public Object lookup(Name p0){ return null; } + public Object lookup(String p0){ return null; } + public ObjectDirectoryMapper getObjectDirectoryMapper(){ return null; } + public boolean authenticate(Name p0, String p1, String p2){ return false; } + public boolean authenticate(Name p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3){ return false; } + public boolean authenticate(Name p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3, AuthenticationErrorCallback p4){ return false; } + public boolean authenticate(Name p0, String p1, String p2, AuthenticationErrorCallback p3){ return false; } + public boolean authenticate(String p0, String p1, String p2){ return false; } + public boolean authenticate(String p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3){ return false; } + public boolean authenticate(String p0, String p1, String p2, AuthenticatedLdapEntryContextCallback p3, AuthenticationErrorCallback p4){ return false; } + public boolean authenticate(String p0, String p1, String p2, AuthenticationErrorCallback p3){ return false; } + public void afterPropertiesSet(){} + public void authenticate(LdapQuery p0, String p1){} + public void bind(DirContextOperations p0){} + public void bind(Name p0, Object p1, Attributes p2){} + public void bind(String p0, Object p1, Attributes p2){} + public void create(Object p0){} + public void delete(Object p0){} + public void list(Name p0, NameClassPairCallbackHandler p1){} + public void list(String p0, NameClassPairCallbackHandler p1){} + public void listBindings(Name p0, NameClassPairCallbackHandler p1){} + public void listBindings(String p0, NameClassPairCallbackHandler p1){} + public void modifyAttributes(DirContextOperations p0){} + public void modifyAttributes(Name p0, ModificationItem[] p1){} + public void modifyAttributes(String p0, ModificationItem[] p1){} + public void rebind(DirContextOperations p0){} + public void rebind(Name p0, Object p1, Attributes p2){} + public void rebind(String p0, Object p1, Attributes p2){} + public void rename(Name p0, Name p1){} + public void rename(String p0, String p1){} + public void search(LdapQuery p0, NameClassPairCallbackHandler p1){} + public void search(Name p0, String p1, NameClassPairCallbackHandler p2){} + public void search(Name p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3){} + public void search(Name p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3, DirContextProcessor p4){} + public void search(Name p0, String p1, int p2, boolean p3, NameClassPairCallbackHandler p4){} + public void search(SearchExecutor p0, NameClassPairCallbackHandler p1){} + public void search(SearchExecutor p0, NameClassPairCallbackHandler p1, DirContextProcessor p2){} + public void search(String p0, String p1, NameClassPairCallbackHandler p2){} + public void search(String p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3){} + public void search(String p0, String p1, SearchControls p2, NameClassPairCallbackHandler p3, DirContextProcessor p4){} + public void search(String p0, String p1, int p2, boolean p3, NameClassPairCallbackHandler p4){} + public void setContextSource(ContextSource p0){} + public void setDefaultCountLimit(int p0){} + public void setDefaultSearchScope(int p0){} + public void setDefaultTimeLimit(int p0){} + public void setIgnoreNameNotFoundException(boolean p0){} + public void setIgnorePartialResultException(boolean p0){} + public void setIgnoreSizeLimitExceededException(boolean p0){} + public void setObjectDirectoryMapper(ObjectDirectoryMapper p0){} + public void unbind(Name p0){} + public void unbind(Name p0, boolean p1){} + public void unbind(String p0){} + public void unbind(String p0, boolean p1){} + public void update(Object p0){} } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairCallbackHandler.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairCallbackHandler.java index 250e6da0237..61bca3585b6 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairCallbackHandler.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairCallbackHandler.java @@ -1,3 +1,10 @@ +// Generated automatically from org.springframework.ldap.core.NameClassPairCallbackHandler for testing purposes + package org.springframework.ldap.core; -public interface NameClassPairCallbackHandler { } +import javax.naming.NameClassPair; + +public interface NameClassPairCallbackHandler +{ + void handleNameClassPair(NameClassPair p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairMapper.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairMapper.java new file mode 100644 index 00000000000..77e36c5ec80 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/NameClassPairMapper.java @@ -0,0 +1,10 @@ +// Generated automatically from org.springframework.ldap.core.NameClassPairMapper for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.NameClassPair; + +public interface NameClassPairMapper +{ + T mapFromNameClassPair(NameClassPair p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/SearchExecutor.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/SearchExecutor.java new file mode 100644 index 00000000000..3783eae738f --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/core/SearchExecutor.java @@ -0,0 +1,11 @@ +// Generated automatically from org.springframework.ldap.core.SearchExecutor for testing purposes + +package org.springframework.ldap.core; + +import javax.naming.NamingEnumeration; +import javax.naming.directory.DirContext; + +public interface SearchExecutor +{ + NamingEnumeration executeSearch(DirContext p0); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/EqualsFilter.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/EqualsFilter.java index a5cbbd2a674..5ac87651711 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/EqualsFilter.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/EqualsFilter.java @@ -2,4 +2,8 @@ package org.springframework.ldap.filter; public class EqualsFilter implements Filter { public EqualsFilter(String attribute, String value) { } + public String encode() { return null; } + public StringBuffer encode(StringBuffer p0) { return null; } + public boolean equals(Object p0) { return false; } + public int hashCode() { return 0; } } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/Filter.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/Filter.java index b24091e6de0..50652cd2361 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/Filter.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/Filter.java @@ -1,4 +1,12 @@ +// Generated automatically from org.springframework.ldap.filter.Filter for testing purposes + package org.springframework.ldap.filter; -public interface Filter { + +public interface Filter +{ + String encode(); + StringBuffer encode(StringBuffer p0); + boolean equals(Object p0); + int hashCode(); } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/HardcodedFilter.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/HardcodedFilter.java index bc43dddc6f8..886e9e89199 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/HardcodedFilter.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/filter/HardcodedFilter.java @@ -2,6 +2,9 @@ package org.springframework.ldap.filter; public class HardcodedFilter implements Filter { public HardcodedFilter(String filter) { } + public String encode() { return null; } public StringBuffer encode(StringBuffer buff) { return buff; } public String toString() { return ""; } + public boolean equals(Object p0) { return false; } + public int hashCode() { return 0; } } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/odm/core/ObjectDirectoryMapper.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/odm/core/ObjectDirectoryMapper.java new file mode 100644 index 00000000000..fae54159cf8 --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/odm/core/ObjectDirectoryMapper.java @@ -0,0 +1,19 @@ +// Generated automatically from org.springframework.ldap.odm.core.ObjectDirectoryMapper for testing purposes + +package org.springframework.ldap.odm.core; + +import javax.naming.Name; +import org.springframework.LdapDataEntry; +import org.springframework.ldap.filter.Filter; + +public interface ObjectDirectoryMapper +{ + T mapFromLdapDataEntry(LdapDataEntry p0, Class p1); + Filter filterFor(Class p0, Filter p1); + Name getCalculatedId(Object p0); + Name getId(Object p0); + String attributeFor(Class p0, String p1); + String[] manageClass(Class p0); + void mapToLdapDataEntry(Object p0, LdapDataEntry p1); + void setId(Object p0, Name p1); +} diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/LdapQuery.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/LdapQuery.java index c94bb75c20c..13e64bf9657 100644 --- a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/LdapQuery.java +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/LdapQuery.java @@ -1,4 +1,17 @@ +// Generated automatically from org.springframework.ldap.query.LdapQuery for testing purposes + package org.springframework.ldap.query; -public interface LdapQuery { +import javax.naming.Name; +import org.springframework.ldap.filter.Filter; +import org.springframework.ldap.query.SearchScope; + +public interface LdapQuery +{ + Filter filter(); + Integer countLimit(); + Integer timeLimit(); + Name base(); + SearchScope searchScope(); + String[] attributes(); } diff --git a/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/SearchScope.java b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/SearchScope.java new file mode 100644 index 00000000000..20d082f60ec --- /dev/null +++ b/java/ql/test/stubs/spring-ldap-2.3.2/org/springframework/ldap/query/SearchScope.java @@ -0,0 +1,11 @@ +// Generated automatically from org.springframework.ldap.query.SearchScope for testing purposes + +package org.springframework.ldap.query; + + +public enum SearchScope +{ + OBJECT, ONELEVEL, SUBTREE; + private SearchScope() {} + public int getId(){ return 0; } +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiCallback.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiCallback.java new file mode 100644 index 00000000000..4b4daf2744e --- /dev/null +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from org.springframework.jndi.JndiCallback for testing purposes + +package org.springframework.jndi; + +import javax.naming.Context; + +public interface JndiCallback +{ + T doInContext(Context p0); +} diff --git a/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiTemplate.java b/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiTemplate.java index 800071a30d4..0f362a0d63b 100644 --- a/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiTemplate.java +++ b/java/ql/test/stubs/springframework-5.3.8/org/springframework/jndi/JndiTemplate.java @@ -1,21 +1,50 @@ +// Generated automatically from org.springframework.jndi.JndiTemplate for testing purposes + package org.springframework.jndi; import java.util.Properties; -import javax.naming.NamingException; +import javax.naming.Context; +import org.apache.commons.logging.Log; +import org.springframework.jndi.JndiCallback; public class JndiTemplate { - public JndiTemplate() {} + protected Context createInitialContext() { + return null; + } - public JndiTemplate(Properties environment) {} + protected final Log logger = null; - public Object lookup(final String name) throws NamingException { - return new Object(); - } + public T execute(JndiCallback p0) { + return null; + } - @SuppressWarnings("unchecked") - public T lookup(String name, Class requiredType) throws NamingException { - return (T) new Object(); - } - - public void setEnvironment(Properties environment) {} + public T lookup(String p0, Class p1) { + return null; + } + + public Context getContext() { + return null; + } + + public JndiTemplate() {} + + public JndiTemplate(Properties p0) {} + + public Object lookup(String p0) { + return null; + } + + public Properties getEnvironment() { + return null; + } + + public void bind(String p0, Object p1) {} + + public void rebind(String p0, Object p1) {} + + public void releaseContext(Context p0) {} + + public void setEnvironment(Properties p0) {} + + public void unbind(String p0) {} } diff --git a/java/ql/test/utils/model-generator/p/Sinks.java b/java/ql/test/utils/model-generator/p/Sinks.java index 8f81d06a8b1..260f235920a 100644 --- a/java/ql/test/utils/model-generator/p/Sinks.java +++ b/java/ql/test/utils/model-generator/p/Sinks.java @@ -7,6 +7,7 @@ import java.nio.file.CopyOption; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; +import java.util.logging.Logger; public class Sinks { @@ -21,4 +22,13 @@ public class Sinks { } } + public static void main(String[] args) throws IOException { + String foo = new Sinks().readUrl(new URL(args[0]), Charset.defaultCharset()); + } + + public void propagate(String s) { + Logger logger = Logger.getLogger(Sinks.class.getSimpleName()); + logger.warning(s); + } + } diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index 4042feb4c70..9389534628f 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -version: 0.0.4 +version: 0.0.6 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql index 0f25497195a..edcd328f712 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/XssATM.ql @@ -23,5 +23,5 @@ where not isFlowLikelyInBaseQuery(source.getNode(), sink.getNode()) and score = getScoreForFlow(source.getNode(), sink.getNode()) select sink.getNode(), source, sink, - "(Experimental) This may be a cross-site scripting vulnerability due to $@. Identified using machine learning." - + "a user-provided value", score + "(Experimental) This may be a cross-site scripting vulnerability due to $@. Identified using machine learning.", + source.getNode(), "a user-provided value", score diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 2a0dd62d1f8..bb7dfce5202 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.0.4 +version: 0.0.6 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index cd465121cb7..57dcf6f2eec 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -998,7 +998,7 @@ module API { * Gets an API node where a RHS of the node is the `i`th argument to this call. */ pragma[noinline] - private Node getAParameterCandidate(int i) { result.getARhs() = getArgument(i) } + private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) } /** Gets the API node for a parameter of this invocation. */ Node getAParameter() { result = this.getParameter(_) } diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 40b2f42822d..278cd0f7d31 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -176,18 +176,13 @@ module DOM { eltName = ["script", "iframe", "embed", "video", "audio", "source", "track"] and attrName = "src" or - ( - eltName = "link" or - eltName = "a" or - eltName = "base" or - eltName = "area" - ) and + eltName = ["link", "a", "base", "area"] and attrName = "href" or eltName = "form" and attrName = "action" or - (eltName = "input" or eltName = "button") and + eltName = ["input", "button"] and attrName = "formaction" ) } diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll index 30bcf82658c..cde984d55ae 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -47,12 +47,7 @@ private DataFlow::SourceNode localDollar() { */ private class ExtendCallWithFlag extends ExtendCall { ExtendCallWithFlag() { - exists(string name | this = DataFlow::moduleImport(name).getACall() | - name = "extend" or - name = "extend2" or - name = "just-extend" or - name = "node.extend" - ) + this = DataFlow::moduleImport(["extend", "extend2", "just-extend", "node.extend"]).getACall() or this = localDollar().getAMemberCall("extend") } diff --git a/javascript/ql/lib/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll index bb723482693..5fe855a46a8 100644 --- a/javascript/ql/lib/semmle/javascript/Externs.qll +++ b/javascript/ql/lib/semmle/javascript/Externs.qll @@ -544,7 +544,7 @@ class ExternalInterface extends ExternalType { } /** - * Externs definition for the Function object. + * The externs definition for the Function object. * * Example: * @@ -561,7 +561,7 @@ class FunctionExternal extends ExternalConstructor { } /** - * Externs definition for the Object object. + * The externs definition for the Object object. * * Example: * @@ -578,7 +578,7 @@ class ObjectExternal extends ExternalConstructor { } /** - * Externs definition for the Array object. + * The externs definition for the Array object. * * Example: * diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index 792cde234ba..6045faca417 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -157,9 +157,7 @@ class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition { */ class AggregateES2015PromiseDefinition extends PromiseCreationCall { AggregateES2015PromiseDefinition() { - exists(string m | m = "all" or m = "race" or m = "any" or m = "allSettled" | - this = getAPromiseObject().getAMemberCall(m) - ) + this = getAPromiseObject().getAMemberCall(["all", "race", "any", "allSettled"]) or this = DataFlow::moduleImport("promise.allsettled").getACall() } @@ -654,10 +652,7 @@ private module ClosurePromise { succ = call and pred = call.getAnArgument() | - name = "all" or - name = "allSettled" or - name = "firstFulfilled" or - name = "race" + name = ["all", "allSettled", "firstFulfilled", "race"] ) or // promise created through goog.promise.withResolver() @@ -712,7 +707,7 @@ private module DynamicImportSteps { */ module Promisify { /** - * Gets a call to a `promisifyAll` function. + * A call to a `promisifyAll` function. * E.g. `require("bluebird").promisifyAll(...)`. */ class PromisifyAllCall extends DataFlow::CallNode { @@ -726,7 +721,7 @@ module Promisify { } /** - * Gets a call to a `promisify` function. + * A call to a `promisify` function. * E.g. `require("util").promisify(...)`. */ class PromisifyCall extends DataFlow::CallNode { diff --git a/javascript/ql/lib/semmle/javascript/Routing.qll b/javascript/ql/lib/semmle/javascript/Routing.qll index 59fc0a814e4..61300f11a42 100644 --- a/javascript/ql/lib/semmle/javascript/Routing.qll +++ b/javascript/ql/lib/semmle/javascript/Routing.qll @@ -137,12 +137,12 @@ module Routing { * this subtree, and subsequently passed on to the successor. */ predicate mayResumeDispatch() { - getLastChild().mayResumeDispatch() + this.getLastChild().mayResumeDispatch() or exists(this.(RouteHandler).getAContinuationInvocation()) or // Leaf nodes that aren't functions are assumed to invoke their continuation - not exists(getLastChild()) and + not exists(this.getLastChild()) and not this instanceof RouteHandler or this instanceof MkRouter @@ -150,7 +150,7 @@ module Routing { /** Gets the parent of this node, provided that this node may invoke its continuation. */ private Node getContinuationParent() { - result = getParent() and + result = this.getParent() and result.mayResumeDispatch() } @@ -170,7 +170,7 @@ module Routing { */ private predicate isFork() { exists(Node child | - child = getAChild() and + child = this.getAChild() and child.mayResumeDispatch() and exists(child.getNextSibling()) ) @@ -184,11 +184,11 @@ module Routing { * that is, a node that has siblings (i.e. multiple children). */ private string getPathFromFork(Node fork) { - isFork() and + this.isFork() and this = fork and result = "" or - exists(Node parent | parent = getParent() | + exists(Node parent | parent = this.getParent() | not exists(parent.getRelativePath()) and result = parent.getPathFromFork(fork) or @@ -205,27 +205,27 @@ module Routing { * that is, a node that has siblings (i.e. multiple children). */ private string getHttpMethodFromFork(Node fork) { - isFork() and + this.isFork() and this = fork and ( - result = getOwnHttpMethod() + result = this.getOwnHttpMethod() or - not exists(getOwnHttpMethod()) and + not exists(this.getOwnHttpMethod()) and result = "*" ) or - result = getParent().getHttpMethodFromFork(fork) and + result = this.getParent().getHttpMethodFromFork(fork) and ( // Only the ancestor restricts the HTTP method - not exists(getOwnHttpMethod()) + not exists(this.getOwnHttpMethod()) or // Intersect permitted HTTP methods - result = getOwnHttpMethod() + result = this.getOwnHttpMethod() ) or // The ancestor allows any HTTP method, but this node restricts it - getParent().getHttpMethodFromFork(fork) = "*" and - result = getOwnHttpMethod() + this.getParent().getHttpMethodFromFork(fork) = "*" and + result = this.getOwnHttpMethod() } /** @@ -256,13 +256,15 @@ module Routing { * Holds if `node` has processed the incoming request strictly prior to this node. */ pragma[inline] - predicate isGuardedByNode(Node node) { isGuardedByNodeInternal(pragma[only_bind_out](node)) } + predicate isGuardedByNode(Node node) { + this.isGuardedByNodeInternal(pragma[only_bind_out](node)) + } /** * Holds if the middleware corresponding to `node` has processed the incoming request strictly prior to this node. */ pragma[inline] - predicate isGuardedBy(DataFlow::Node node) { isGuardedByNode(getNode(node)) } + predicate isGuardedBy(DataFlow::Node node) { this.isGuardedByNode(getNode(node)) } /** * Gets an HTTP method name which this node will accept, or nothing if the node accepts all HTTP methods, not @@ -271,16 +273,16 @@ module Routing { HTTP::RequestMethodName getOwnHttpMethod() { none() } // Overridden in subclass private Node getAUseSiteInRouteSetup() { - if getParent() instanceof RouteSetup + if this.getParent() instanceof RouteSetup then result = this - else result = getParent().getAUseSiteInRouteSetup() + else result = this.getParent().getAUseSiteInRouteSetup() } /** Gets a place where this route node is installed as a route handler. */ Node getRouteInstallation() { - result = getAUseSiteInRouteSetup() + result = this.getAUseSiteInRouteSetup() or - not exists(getAUseSiteInRouteSetup()) and + not exists(this.getAUseSiteInRouteSetup()) and result = this } @@ -352,7 +354,7 @@ module Routing { Node getChild(int n) { none() } /** Gets the number of children of this route node. */ - final int getNumChild() { result = count(int n | exists(getChild(n))) } + final int getNumChild() { result = count(int n | exists(this.getChild(n))) } /** * Gets a path prefix to be matched against the path of incoming requests. @@ -416,7 +418,7 @@ module Routing { * Gets a data flow node that flows to this use-site in one step. */ DataFlow::Node getSource() { - result = getALocalSource() + result = this.getALocalSource() or StepSummary::smallstep(result, this, routeStepSummary()) or @@ -425,7 +427,7 @@ module Routing { RouteHandlerTrackingStep::step(result, this) or exists(string prop | - StepSummary::smallstep(result, getSourceProp(prop).getALocalUse(), StoreStep(prop)) + StepSummary::smallstep(result, this.getSourceProp(prop).getALocalUse(), StoreStep(prop)) ) or this = getAnEnumeratedArrayElement(result) @@ -435,32 +437,32 @@ module Routing { private DataFlow::SourceNode getSourceProp(string prop) { StepSummary::step(result, this, LoadStep(prop)) or - StepSummary::step(result, getSourceProp(prop), routeStepSummary()) + StepSummary::step(result, this.getSourceProp(prop), routeStepSummary()) or - StepSummary::step(result, getSourceProp(prop), CopyStep(prop)) + StepSummary::step(result, this.getSourceProp(prop), CopyStep(prop)) or exists(string oldProp | - StepSummary::step(result, getSourceProp(oldProp), LoadStoreStep(prop, oldProp)) + StepSummary::step(result, this.getSourceProp(oldProp), LoadStoreStep(prop, oldProp)) ) } private DataFlow::Node getStrictSource() { - result = getSource() and + result = this.getSource() and result != this } final override Routing::Node getChild(int n) { n = 0 and - result = MkValueNode(getStrictSource()) + result = MkValueNode(this.getStrictSource()) or // If we cannot find the source of the use-site, but we know it's somehow a reference to a router, // treat the router as the source. This is needed to handle chaining calls on the router, as the // specific framework model knows about chaining steps, but the general `getSource()` predicate doesn't. n = 0 and - not exists(getStrictSource()) and + not exists(this.getStrictSource()) and exists(Router::Range router | this = router.getAReference().getALocalUse() and - result = MkRouter(router, getContainer()) + result = MkRouter(router, this.getContainer()) ) } } @@ -483,7 +485,7 @@ module Routing { */ abstract DataFlow::Node getArgumentNode(int n); - final override Node getChild(int n) { result = MkValueNode(getArgumentNode(n)) } + final override Node getChild(int n) { result = MkValueNode(this.getArgumentNode(n)) } } /** An argument to a `WithArguments` instance, seen as a use site. */ @@ -497,7 +499,7 @@ module Routing { private class ImpliedArrayRoute extends ValueNode::WithArguments, DataFlow::ArrayCreationNode { ImpliedArrayRoute() { this instanceof ValueNode::UseSite } - override DataFlow::Node getArgumentNode(int n) { result = getElement(n) } + override DataFlow::Node getArgumentNode(int n) { result = this.getElement(n) } } } @@ -521,10 +523,10 @@ module Routing { * A node in the routing tree which has no parent. */ class RootNode extends Node { - RootNode() { not exists(getParent()) } + RootNode() { not exists(this.getParent()) } /** Gets a node that is part of this subtree. */ - final Node getADescendant() { result = getAChild*() } + final Node getADescendant() { result = this.getAChild*() } } /** @@ -546,7 +548,7 @@ module Routing { * * This is an alias for `getParent`, but may be preferred for readability. */ - final Node getRouter() { result = getParent() } + final Node getRouter() { result = this.getParent() } } /** @@ -568,7 +570,7 @@ module Routing { Node getChild(int n) { none() } /** Gets the number of children of this route node. */ - final int getNumChild() { result = count(int n | exists(getChild(n))) } + final int getNumChild() { result = count(int n | exists(this.getChild(n))) } /** * Gets a path prefix to be matched against the path of incoming requests. @@ -630,13 +632,13 @@ module Routing { * This class can be extended to contribute new kinds of route handlers. */ abstract class MethodCall extends RouteSetup::Range, DataFlow::MethodCallNode { - override Node getChild(int n) { result = MkValueNode(getChildNode(n)) } + override Node getChild(int n) { result = MkValueNode(this.getChildNode(n)) } /** Gets the `n`th child of this route setup. */ - DataFlow::Node getChildNode(int n) { result = getArgument(n) } + DataFlow::Node getChildNode(int n) { result = this.getArgument(n) } override predicate isInstalledAt(Router::Range router, ControlFlowNode cfgNode) { - this = router.getAReference().getAMethodCall() and cfgNode = getEnclosingExpr() + this = router.getAReference().getAMethodCall() and cfgNode = this.getEnclosingExpr() } } @@ -679,14 +681,14 @@ module Routing { result.isInstalledAt(router, any(ControlFlowNode cfg | cfg.getContainer() = container)) } - override Node getAChild() { result = MkRouteSetup(getARouteSetup()) } + override Node getAChild() { result = MkRouteSetup(this.getARouteSetup()) } override Node getLastChild() { result = getMostRecentRouteSetupAt(router, container.getExit()) } override Node getFirstChild() { - result = getAChild() and not exists(result.getPreviousSibling()) + result = this.getAChild() and not exists(result.getPreviousSibling()) } } } @@ -753,14 +755,14 @@ module Routing { ImpliedRouteSetup() { FlowSteps::calls(this, target) and routerIsLiveInContainer(router, target) and - routerIsLiveInContainer(router, getContainer()) + routerIsLiveInContainer(router, this.getContainer()) } override Routing::Node getChild(int n) { result = MkRouter(router, target) and n = 0 } override predicate isInstalledAt(Router::Range r, ControlFlowNode cfgNode) { r = router and - cfgNode = getEnclosingExpr() + cfgNode = this.getEnclosingExpr() } } @@ -799,11 +801,11 @@ module Routing { * if the default behavior is inadequate for that framework. */ DataFlow::CallNode getAContinuationInvocation() { - result = getAParameter().ref().getAnInvocation() and + result = this.getAParameter().ref().getAnInvocation() and result.getNumArgument() = 0 or result.(DataFlow::MethodCallNode).getMethodName() = "then" and - result.getArgument(0) = getAParameter().ref().getALocalUse() + result.getArgument(0) = this.getAParameter().ref().getALocalUse() } } @@ -827,11 +829,11 @@ module Routing { t.start() and result = this or - exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t)) } /** Gets a data flow node referring to this route handler parameter. */ - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) } /** * Gets the corresponding route handler, that is, the function on which this is a parameter. diff --git a/javascript/ql/lib/semmle/javascript/StringOps.qll b/javascript/ql/lib/semmle/javascript/StringOps.qll index 31190f6cf12..04959341720 100644 --- a/javascript/ql/lib/semmle/javascript/StringOps.qll +++ b/javascript/ql/lib/semmle/javascript/StringOps.qll @@ -512,7 +512,7 @@ module StringOps { } /** - * One of the operands in a string concatenation. + * An operand in a string concatenation. * * Examples: * ``` diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index 4ba6aed174c..d0e6d351fe1 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -1644,7 +1644,7 @@ class EnumMember extends ASTNode, @enum_member { } /** - * Scope induced by an interface declaration, containing the type parameters declared on the interface. + * A scope induced by an interface declaration, containing the type parameters declared on the interface. * * Interfaces that do not declare type parameters have no scope object. */ @@ -1653,7 +1653,7 @@ class InterfaceScope extends @interface_scope, Scope { } /** - * Scope induced by a type alias declaration, containing the type parameters declared the the alias. + * A scope induced by a type alias declaration, containing the type parameters declared the the alias. * * Type aliases that do not declare type parameters have no scope object. */ @@ -1662,14 +1662,14 @@ class TypeAliasScope extends @type_alias_scope, Scope { } /** - * Scope induced by a mapped type expression, containing the type parameter declared as part of the type. + * A scope induced by a mapped type expression, containing the type parameter declared as part of the type. */ class MappedTypeScope extends @mapped_type_scope, Scope { override string toString() { result = "mapped type scope" } } /** - * Scope induced by an enum declaration, containing the names of its enum members. + * A scope induced by an enum declaration, containing the names of its enum members. * * Initializers of enum members are resolved in this scope since they can reference * previously-defined enum members by their unqualified name. @@ -2637,7 +2637,7 @@ class TypeofType extends Type, @typeof_type { } /** - * One of two values indicating if a signature is a function or constructor signature. + * A value indicating if a signature is a function or constructor signature. */ class SignatureKind extends string { SignatureKind() { this = "function" or this = "constructor" } diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll index 76f3b3cb022..dc76884b73c 100755 --- a/javascript/ql/lib/semmle/javascript/XML.qll +++ b/javascript/ql/lib/semmle/javascript/XML.qll @@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } + predicate hasAttribute(string name) { exists(this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index c8c2fcc35c6..a2a38b47c8b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -694,15 +694,13 @@ module TaintTracking { ) or // `(encode|decode)URI(Component)?` propagate taint - exists(DataFlow::CallNode c, string name | + exists(DataFlow::CallNode c | succ = c and - c = DataFlow::globalVarRef(name).getACall() and + c = + DataFlow::globalVarRef([ + "encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent" + ]).getACall() and pred = c.getArgument(0) - | - name = "encodeURI" or - name = "decodeURI" or - name = "encodeURIComponent" or - name = "decodeURIComponent" ) or // In and out of .replace callbacks diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll index 0e83d544fd3..f69d25b3a60 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll @@ -15,7 +15,7 @@ private import semmle.javascript.internal.CachedStages private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyName prop) /** - * Summary of the steps needed to track a value to a given dataflow node. + * A summary of the steps needed to track a value to a given dataflow node. * * This can be used to track objects that implement a certain API in order to * recognize calls to that API. Note that type-tracking does not by itself provide a @@ -182,7 +182,7 @@ module TypeTracker { private newtype TTypeBackTracker = MkTypeBackTracker(Boolean hasReturn, OptionalPropertyName prop) /** - * Summary of the steps needed to back-track a use of a value to a given dataflow node. + * A summary of the steps needed to back-track a use of a value to a given dataflow node. * * This can be used to track callbacks that are passed to a certain API call, and are * therefore expected to be called with a certain type of value. diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll index 1662a0055b1..4986164f859 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll @@ -157,7 +157,7 @@ private class AnalyzedImport extends AnalyzedPropertyRead, DataFlow::ValueNode { exports = MkAbstractProperty(TAbstractModuleObject(imported), "exports") | base = exports.getALocalValue() and - propName = astNode.(ImportSpecifier).getImportedName() + propName = astNode.getImportedName() ) or // when importing CommonJS/AMD modules from ES2015, `module.exports` appears @@ -168,7 +168,7 @@ private class AnalyzedImport extends AnalyzedPropertyRead, DataFlow::ValueNode { // CommonJS/AMD module generated by TypeScript compiler imported.getAStmt() instanceof ExportAssignDeclaration ) and - astNode.(ImportSpecifier).getImportedName() = "default" and + astNode.getImportedName() = "default" and base = TAbstractModuleObject(imported) and propName = "exports" } diff --git a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll index 1d28a29df8f..0eed07a6962 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll @@ -75,7 +75,9 @@ abstract class FrameworkLibraryInstance extends TopLevel { * via the `src` attribute of a `